こんにちは、KID.Aです。
前回の記事ではペリフェラルのアドバタイジングデータの発信を実装しました。
今回はペリフェラルのデータ通信の実装をしていきます。
まずは、データ通信を行う際はアドバタイジングで設定するsetConnectableをtrueにします。
AdvertiseSettings.Builder settingBuilder = new AdvertiseSettings.Builder(); settingBuilder.setConnectable(true);
これでデータ通信が可能になります。
BluetoothGattServerの実装
ペリフェラルにはBluetoothGattServerを使用してサービス登録やデータのやり取りを行います。
・開発サイトのAPI
http://developer.android.com/intl/ja/reference/android/bluetooth/BluetoothGattServer.html
以下のように実装します。
BluetoothGattServer gattServer; BluetoothDevice mDevice; BluetoothGattCharacteristic mCharacteristic; public void setGattServer() { BluetoothManager manager = (BluetoothManager) getSystemService(Context.BLUETOOTH_SERVICE); // GattServer gattServer = manager.openGattServer(getApplicationContext(), new BluetoothGattServerCallback() { @Override public void onCharacteristicWriteRequest(BluetoothDevice device, int requestId, BluetoothGattCharacteristic characteristic, boolean preparedWrite, boolean responseNeeded, int offset, byte[] value) { super.onCharacteristicWriteRequest(device, requestId, characteristic, preparedWrite, responseNeeded, offset, value); if (value != null) { Log.d("TAG", "value ~ " + new String(value)); } gattServer.sendResponse(device, requestId, BluetoothGatt.GATT_SUCCESS, offset, null); } @Override public void onCharacteristicReadRequest(BluetoothDevice device, int requestId, int offset, BluetoothGattCharacteristic characteristic) { super.onCharacteristicReadRequest(device, requestId, offset, characteristic); gattServer.sendResponse(device, requestId, BluetoothGatt.GATT_SUCCESS, offset, "ABC".getBytes()); } @Override public void onConnectionStateChange(BluetoothDevice device, int status, int newState) { super.onConnectionStateChange(device, status, newState); if (newState == BluetoothProfile.STATE_CONNECTED) { mDevice = device; } else if (newState == BluetoothProfile.STATE_DISCONNECTED) { mDevice = null; } } }); //Serviceを登録 BluetoothGattService service = new BluetoothGattService( UUID.fromString(“ServiceのUUID"), BluetoothGattService.SERVICE_TYPE_PRIMARY); mCharacteristic = new BluetoothGattCharacteristic( UUID.fromString(“CharacteristicのUUID"), BluetoothGattCharacteristic.PROPERTY_NOTIFY | BluetoothGattCharacteristic.PROPERTY_READ | BluetoothGattCharacteristic.PROPERTY_WRITE, BluetoothGattCharacteristic.PERMISSION_READ | BluetoothGattCharacteristic.PERMISSION_WRITE); service.addCharacteristic(mCharacteristic); gattServer.addService(service); }
BluetoothGattServerはBluetoothManager#openGattServerから取得します。
引数にはコンテキストとBluetoothGattServerCallbackが必要となります。BluetoothGattServerCallbackの説明はwrite/read/notifyの実装で説明します。
BluetoothGattServerのインスタンスが取得できたら、BluetoothManager#addServiceでサービスを登録します。
これで実装は完了です。
前回の記事のアドバタイズの開始前にsetGattServerのメソッドを実行させればOKです。
この状態でセントラルからBluetoothDevice#connectGatt(iOSはCBcentralManager#connectPeripheral)が呼ばれるとペリフェラルのBluetoothGattServerCallback#onConnectionStateChangeがコールバックされ接続したデバイスがわかります。
ちなみにセントラルの実装はこちらの記事に記載しています。
http://blog.techfirm.co.jp/2014/04/30/ios-bluetooth-leでデータのやりとり/
http://blog.techfirm.co.jp/2014/05/08/androidとios間のデータのやりとりをbluetooth-leで行う/
writeの実装について
定義したServiceにセントラルからwriteが呼ばれるとBluetoothGattServerCallback#onCharacteristicWriteRequestが呼ばれます。
valueに送信されたデータが入ります。
readの実装について
定義したServiceにセントラルからreadが呼ばれるとBluetoothGattServerCallback#onCharacteristicReadRequestが呼ばれます。
下記のコードで返答します。
gattServer.sendResponse(device, requestId, BluetoothGatt.GATT_SUCCESS, offset, "ABC".getBytes());
notifyの実装について
BluetoothGattServerCallback#onConnectionStateChangeに接続されたデバイスが通知されるので、そのデバイスを覚えておきます。
if (newState == BluetoothProfile.STATE_CONNECTED) { mDevice = device; } else if (newState == BluetoothProfile.STATE_DISCONNECTED) { mDevice = null; }
その後、以下のように送信したいデバイスにBluetoothGattServer#notifyCharacteristicChangedで通知します。
下記の契機はボタンが押された場合に通知するコードになります。
findViewById(R.id.button).setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { mCharacteristic.setValue("ABC".getBytes()); gattServer.notifyCharacteristicChanged(mDevice, mCharacteristic, false); } });
以上がペリフェラルのデータ通信の実装になります。