AndroidとiOS間のデータのやりとりをBluetooth LEで行う

こんにちは、ゴールデンウィークは引きこもって大好きな映画を見ていたmanaです。

今回は、AndroidとiOSを使用して、Bluetooth LEを使ってデータのやりとりを行います。
といっても、「[iOS] Bluetooth LEでデータのやりとり」でiOSのBluetooth LEの使い方を説明しましたので、AndroidのBluetooth LEの使い方の説明がメインになります。
Bluetooth LEの説明については「AndroidでiBeaconを発見する」を参照してください。

ペリフェラルとセントラルについて

Androidは現在、ペリフェラルになれません。Androidを使用する場合はセントラルとしてしか使用できません。
※Android5.0からアドバタイジングできるようになり、ペリフェラル側の実装ができます。以下の記事で紹介しています。
ペリフェラル側のアドバタジング発信
ペリフェラル側のデータ通信実装


※ペリフェラル、セントラルの説明は「[iOS] Bluetooth LEでデータのやりとり」を参照してください。

ペリフェラルと接続する

iOSをペリフェラルにして、Androidをセントラルにしてデータのやり取りを行います。

・iOSをペリフェラルにする
[iOS] Bluetooth LEでデータのやりとり」のiOSで接続する、ペリフェラルの実装を参考にしてください。

・Androidのセントラルの実装方法

1. BluetoothをActivityで使用できるようにする。

     Intent enableBtIntent = new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE);
     startActivityForResult(enableBtIntent, REQUEST_ENABLE_BT);

2. BluetoothManagerからBluetoothAdapterを取得します。

     BluetoothManager bluetoothManager = (BluetoothManager) getSystemService(Context.BLUETOOTH_SERVICE);
     BluetoothAdapter mBluetoothAdapter = bluetoothManager.getAdapter();

3. BluetoothAdapterのstartLeScanを呼び出す。

     mBluetoothAdapter.startLeScan(mLeScanCallback);

4. BluetoothAdapter.LeScanCallbackのonLeScanに結果が返ってくる。

    private BluetoothAdapter.LeScanCallback mLeScanCallback =
        new BluetoothAdapter.LeScanCallback() {
               @Override
                public void onLeScan(final BluetoothDevice device, final int rssi, final byte[] scanRecord) {
                }
        }

ここまでは「AndroidでiBeaconを発見する」でも説明しています。
※Android5.0からBluetoothLeScannerでも検索できるようになりました(BluetoothLeScannerについてを参照)

5. LeScanCallback#onLeScanで受け取ったBluetoothDevice#getAddressでアドレスを取得する。

      public void onLeScan(final BluetoothDevice device, final int rssi, final byte[] scanRecord) {
         String address = device.getAddress();
      }

6. アドレスからデバイスを検索して、接続する。

     BluetoothDevice device = mBluetoothAdapter.getRemoteDevice(address);
     BluetoothGatt mBluetoothGatt = device.connectGatt(this, false, mGattCallback);

第一引数のthisはコンテキストです。第二引数はfalseは直接接続、trueは自動接続になるため、直接接続する際はfalseにします。第三引数はコールバックになります(7で説明します)。

7. BluetoothGattCallback#onConnectionStateChangeにstatusが成功が返ってくれれば接続が成功します。

     private final BluetoothGattCallback mGattCallback = new BluetoothGattCallback() {
        @Override
        public void onConnectionStateChange(BluetoothGatt gatt, int status, int newState) {
        }

        @Override
        public void onServicesDiscovered(BluetoothGatt gatt, final int status) {
        }
        
        // 他にもOverrideできるメソッドがあるが省略
    };

8. 接続完了後、ペリフェラルのサービス一覧がBluetoothGattCallback#onServicesDiscoveredに来ます。このサービス一覧を使用して、ペリフェラルとデータのやり取りができるようになります。

データのやりとり[write]

1. BluetoothGattCallback#onServicesDiscoveredで書きたいサービスを保存しておきます。

     BluetoothGattService myService = gatt.getService(UUID.fromString("自分で定義したサービスのUUID"));
     BluetoothGattCharacteristic myChar = confirmService.getCharacteristic(UUID.fromString("自分で定義したキャラクリスティックのUUID"));

2. 送るデータを設定する。

     myChar.setValue("送るデータ");

3. データをペリフェラルに送る。

     mBluetoothGatt.writeCharacteristic(myChar);

データのやりとり[read]

1. BluetoothGattCallback#onServicesDiscoveredで読みたいサービスを保存しておきます。

     BluetoothGattService myService = gatt.getService(UUID.fromString("自分で定義したサービスのUUID"));
     BluetoothGattCharacteristic myChar = confirmService.getCharacteristic(UUID.fromString("自分で定義したキャラクリスティックのUUID"));

2. データをペリフェラルから読み込み。

     mBluetoothGatt.readCharacteristic(myChar);

3. ペリフェラルからデータが返答される。BluetoothGattCallback#onCharacteristicReadに通知される。

4. 送られてきたデータの取得をする。onCharacteristicReadの引数のBluetoothGattCharacteristicから読み取れる。

     final byte[] data = characteristic.getValue()

データのやりとり[notification]

1. BluetoothGattCallback#onServicesDiscoveredで通知のサービスを保存しておきます。

     BluetoothGattService myService = gatt.getService(UUID.fromString("自分で定義したサービスのUUID"));
     BluetoothGattCharacteristic myChar = confirmService.getCharacteristic(UUID.fromString("自分で定義したキャラクリスティックのUUID"));

2. 通知を設定します。

     BluetoothGattDescriptor descriptor = characteristic.getDescriptor(UUID.fromString("00002902-0000-1000-8000-00805f9b34fb"));
     descriptor.setValue(BluetoothGattDescriptor.ENABLE_NOTIFICATION_VALUE);

3. ペリフェラルから通知がきた場合。BluetoothGattCallback#onCharacteristicChangedが呼ばれる。値は引数のBluetoothGattCharacteristicから読み取れる。

     final byte[] data = characteristic.getValue()

AndroidのDeveloperページにBluetooth LEの実装方法がのっているので参考にしてください。
・参考ページ
http://developer.android.com/guide/topics/connectivity/bluetooth-le.html

これでiOSとAndroid間でBluetooth LEを使用してデータのやりとりができます。
ただし、Nexus 5で試したところ、notificationを複数設定しても最初に設定したものしか反映されなかったり、Androidか端末依存なのかわかりませんが、制限がありそうです。(iPhone 5S iOS7では複数のnotificationを設定できました。)

mana

mana の紹介

好きな映画は「影武者」で、好きな映画監督は「岩井俊二」です。 岩井作品では、「PiCNiC 」「スワロウテイル 」「花とアリス」が好きです。 (。・_・。)ノ
カテゴリー: Android タグ: , , , パーマリンク

コメントを残す

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