[Android 5.0] BLE ペリフェラル側のデータ通信実装

こんにちは、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はAPI Lv18で4.3からですね。なのでデータ通信自体は4.3からできますが、アドバタイジングしないと接続契機がないような気がします。。。

 

以下のように実装します。

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);
    }
});

 

以上がペリフェラルのデータ通信の実装になります。

 

 

KID.A

KID.A の紹介

楽して生きることと一発逆転を夢見ている、ちゃきちゃきのAndroiderです。 いろいろアプリを出しているのですが、いつもリリース後にターゲットユーザ数を2桁見誤っていたことに気付くので、残念でなりません。下方修正で、ヒットがでません。おしいです。 明日から本気出します。 よろしくお願いします。
カテゴリー: Android タグ: , , , パーマリンク

コメントを残す

メールアドレスが公開されることはありません。 * が付いている欄は必須項目です