Android-BLE-Library
こんにちは、アプリケーションエンジニアの難波です。
BraveridgeではIoTデバイスを製作する時によくNordic社のSoCを使用しています。
そのNordic社はAndroid用のBLEライブラリをOSSとしてリリースしています。
AndroidアプリでBLE機能を実装しようとすると、OSのバージョンや機種依存、ハマりやすいポイント等があったりと結構クセが強いです。
NordicのAndroid用BLEライブラリはその辺りを良い感じに吸収してくれています。
今回は Android-BLE-Library のCentralに関連する機能を実装例と共に紹介します。
実装例
Centralを実装する時に BLEデバイスのスキャン と BLEデバイスに接続して制御 という2機能を実装する必要があります。
このライブラリは BLEデバイスへの接続と制御 を担当します。
Android-BLE-LibraryはCentralだけでなくPeripheralを実装する場合にも利用することができます。
1. BleManager を継承したclassを実装します。
このclassでBLEデバイスへの接続・切断とcharacteristicのread、write、notifyのcallbackを実装します。
class SampleBleManager(context: Context) : BleManager(context) {
var discoveredServicesHandler: ((List<BluetoothGattService>) -> Unit)? = null
private var gattCallback: BleManagerGattCallback? = null
private inner class SampleBleManagerGattCallback: BleManagerGattCallback() {
// Peripheral接続後にコールされる
public override fun isRequiredServiceSupported(gatt: BluetoothGatt):Boolean {
discoveredServicesHandler?.apply { this(gatt.services) }
return true
}
override fun onDeviceDisconnected() {}
}
// 親クラスのコンストラクタでコールされる
override fun getGattCallback() = gattCallback ?: run {
gattCallback = SampleBleManagerGattCallback()
gattCallback!!
}
}
BleManagerGattCallback の実装
まず BleManagerGattCallback を実装します。(SampleBleManagerGattCallbackクラス)
BLE接続が完了すると isRequiredServiceSupported(gatt) がコールされます。
この時点で接続したPeripheralのServiceリストを取得しているので、discoveredServicesHandler でViewModelやActivityなど呼び出し側に伝えます。
getGattCallback() の実装
次に getGattCallback() を実装します。
このメソッドは親クラスのコンストラクタでコールされるので、SampleBleManagerクラス のコンストラクタよりも先に getGattCallback() が呼ばれます。
そのため gattCallbackプロパティ をnullチェックして、初回コール時のみ SampleBleManagerGattCallbackクラス をインスタンス化しています。
val connectionObserver = object: BaseConnectionObserver {}
// ↑ BaseConnectionObserver は ConnectionObserver の各メソッドをデフォルト実装したインターフェース
val bleManager: SampleBleManager by lazy {
val manager = SampleBleManager(app)
manager.setConnectionObserver(connectionObserver)
manager.discoveredServicesHandler = { services ->
services.forEach { Log.d(TAG, it.uuid.toString()) }
}
manager
}
// Peripheralに接続する
val bluetoothDevice: BluetoothDevice // BLEスキャンで取得したBluetoothDeviceインスタンス
bleManager.connect(bluetoothDevice).enqueue()
// Peripheralとの接続を切断する
bleManager.disconnect().enqueue()
実装した SampleBleManagerクラス をインスタンス化してPeripheralに接続します。
BleManagerクラス では以下の機能が実装されているので、SampleBleManagerクラス で簡単に利用する事ができます。
- RSSIの取得
- characteristicの操作(read、write、notifyのcallback)
- MTUの変更
- ボンディング(ペアリング)
メリット
よくある実装ミスとして、Peripheralへ上記操作を複数同時並行にリクエストしてしまい、Peripheral側がいくつかのリクエストをスルーしてしまう事があります。
BleManagerクラス では内部にリクエストキューを実装しているので、必ずシーケンシャルに実行してくれます。
こういった機能はとてもありがたいです。
サンプルアプリを含めたソースコード全体は github で確認できます。