こんにちは、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);
}
});
以上がペリフェラルのデータ通信の実装になります。