OE_uia Tech Blog

ScalaMatsuri / Scala / Android / Bioinfomatics

そこまで怖くないAndroid BLE

| Comments

これはBLE Advent Calendar 2015 7日目の記事です。

AndroidのBluetooth Low Energy(BLE)について、どんなイメージをお持ちでしょうか?

安定してない?わかりにくい?

色々と怖いイメージをもたれがちと思います。確かに怖いところも色々とありますが、今ちょうどAndroid BLEをフルに使ったプロダクトBONX -Wearable Walkie-Talkie-を開発しているので、そこで溜まった知見を共有できればと思います。

BLEの基礎

BLEは、接続する2デバイス間の関係が明確に分かれています。CentralとPeripheralです。

-役割- -Central- -Peripheral-
動作 Scan Advertise
GATT Client Server
version 4.3~ 5.0~

BLE機能の使用方法

まず、以下のpermissionとfeatureが必要になります。

1
2
3
<uses-permission android:name="android.permission.BLUETOOTH" />
<uses-permission android:name="android.permission.BLUETOOTH_ADMIN" />
<uses-feature android:name="android.hardware.bluetooth_le" android:required="true"/>

Android 6.0から、以下のpermission(ACCESS_FINE_LOCATIONでも可)が必要になる上に、更にユーザーに明示的に位置情報使用許可 をもらう必要が有ります(iOSっぽいですね)。

1
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />

使用許可は、以下のように求めましょう。許可を求めるDialogが表示され、一度許可をもらえば、その後はずっと(端末の設定で明示的にOFFにされない限り)有効です。

1
2
3
4
5
6
7
8
9
10
11
12
public class MyActivity extends Activity{
   ....
   requestPermissions(new String[]{Manifest.permission.ACCESS_COURSE_LOCATION}, REQUEST_CODE)
   ...
   @Override
   public void onRequestPermissionsResult(int requestCode, String permissions[], int[] grantResults){
       if(requestCode == REQUEST_CODE)
       {
           ...
       }
   }
}

Bluetooth Low Energy startScan on Android 6.0 does not find devices - Stack Overflow

BLE Central機能

Android 4.3から、BLE Central機能のサポートを開始しました。

BLE Central機能で使うクラス,メソッド

Android 4.4以下(API Level 20以下)ではBluetoothAdapter#startLeScanを使います。

Android 5.0以上(API Level 21以上)では先の旧APIはdeprecatedになっていますので、BluetoothAdapter#getBluetoothLeScannerからのBluetoothLeScanner#startScanを使います。

5.0以上のほうが、ScanSettingsや、より細かなScanFilterを指定できたり、AdvertisePacketの中身を生byte列ではなくScanResultで取得できたりと、柔軟性高く利用できます。

APIの使いやすさもそうですが、Android 4.3, Android 4.4ではBLE Central機能があまり安定していない(よく接続やRead/Writeに失敗するし、遅い)ので、注意してください。

BLE Central実験用アプリ

iOS BLEテスト用アプリといえば、Light Blueがデファクトだと思いますが、AndroidでCentral機能を試すときはBLE Scanner: Read,Write,Notifyです。

BLE CentralのWrite, Read, Notificationといった基礎機能を全て安定して使うことができますので、テストによく使います。

その他注意というかBad Know-How

  • BLE接続機能の安定性は端末差が大きい

おおよその端末でBLE Scan自体は比較的安定しているのですが、BLE接続、具体的には接続にかかる時間及びRead/Writeの成功率には個体差が大きいです。

接続・切断処理を短時間の間に繰り返すアプリを作る場合は注意してください。

  • BLEのOSキャッシュにより、長時間使用していると謎の挙動を示すことがある

具体的には、BLE接続に失敗する、ないしはRead /Writeに失敗する確率が上がる、などです。

そうなった場合は、まずBluetooth ON/OFFを試して、もしダメなら端末再起動すると直ります。

  • BLE characteristicに書き込む値のENDIANに注意する。

BLEアプリを作る場合、大抵はクロスプラットフォーム(というかiOSで作っていて、そのAndroid版を作りたい場合)が多いと思います。

その場合は、ENDIANには注意してください。iOSはcharacteristicにはLITTLE ENDIANで読み書きする一方、AndroidはBIG ENDIANです。

startLeScanで見つかったデバイスに対しても、Classic BTを接続を試みている?っぽいのが原因の模様です。

Issue 58942 - android - BluetoothDevice.connectGATT Will Not Connect to BluetoothDevice.DEVICE_TYPE_DUAL - Android Open Source Project - Issue Tracker - Google Project Hosting

Dual-mode issue when connecting Android BLE - Google グループ

BLE Peripheral機能

Android 5.0から、OS上はBLE Peripheralのサポートを開始しました。

しかしながら、何故か現在使われているBluedroidというBluetoothプロトコル・スタックでは、Broadcom製のチップセットのHCIコマンドmultiple advertisementに依存しており、端末が搭載しているチップセットによってはBLE Peripheral機能が使えません。

bluetooth - Android 5.0でBLE advertising するための要件 - Qiita

BLE Peripheral機能を使えるかどうかは、以下のように判定できますので、チェックしましょう。但し端末がAdvertiseをサポートしていても、BluetoothがOFFになっているとき(BluetoothAdapter#isEnabledがfalseのとき)は以下もfalseを返すことに注意してください。

1
2
3
4
5
6
7
public boolean isCapableToAdvertise(BluetoothAdapter bAdapter){
return Build.VERSION.SDK_INT > 20 &&
     null != bAdapter.getBluetoothLeAdvertiser() &&
     bAdapter.isMultipleAdvertisementSupported() &&
     bAdapter.isOffloadedFilteringSupported() &&
     bAdapter.isOffloadedScanBatchingSupported();
}

AndroidでBLEのAdvertise modeを使えるかどうかのメモ - Qiita

BLE Peripheral機能が使える端末のリストは、以下が一番まとまっていると思います。

Android Beacon Library

ここにない端末で言えば、Galaxy S6, Zenfone 2 Laser, Galazy S5 Active, Nexus 6PなどはAdvertiseに対応しています。

BLE Peripheral機能で使うクラス、メソッド

GattServerの初期化はBluetoothManager#openGattServerから行います。

Advertiseの開始はBluetoothAdapter#getBluetoothLeAdvertiserからのBluetoothLeAdvertiser#startAdvertisingを使います。

BLE Peripheral機能の諸注意

不要な場合は、inludeするのをやめましょう。

最後に

Android BLE機能についてざくっと紹介しましたが、いかがでしょうか。

色々バグがあったりクセがあったりして確かに扱いにくいとは思いますが、頑張れば対応できるレベルだと思います。

まだまだ開発しながらノウハウを貯めている段階ですので、もし間違いなどあればぜひ@OE_uiaに教えてください。よろしくお願いします。

Comments