Android-BLE-Library (Peripheral)

こんにちは、アプリケーションエンジニアの難波です。

BraveridgeではIoTデバイスを製作する時によくNordic社のSoCを使用しています。
そのNordic社はAndroid用のBLEライブラリをOSSとしてリリースしています。

AndroidアプリでBLE機能を実装しようとすると、OSのバージョンや機種依存、ハマりやすいポイント等があったりと結構クセが強いです。
NordicのAndroid用BLEライブラリはその辺りを良い感じに吸収してくれています。

  1. Android-Scanner-Compat-Library
  2. Android-BLE-Library

今回は Android-BLE-Library のPeripheralに関連する機能を実装例と共に紹介します。

実装例

BleServerManager の継承

Centralの場合と比べて少し複雑になります。

まず BleServerManager を継承したclassを実装します。
このclassでPeripheralのProfileを定義します。


class SampleBleServerManager(private val context: Context) 
    : BleServerManager(context) {

    val characteristicForRead = characteristic(
        UUID.randomUUID(), 
        BluetoothGattCharacteristic.PROPERTY_READ, 
        BluetoothGattCharacteristic.PERMISSION_READ
    ).apply {
        value = byteArrayOf(0x1)
    }
    private val serviceUUID = UUID.randomUUID()

    override fun initializeServer() = listOf(service(serviceUUID, characteristicForRead))
}



initializeServer() の戻り値がBLE接続時にCentralが取得するServiceリストになります。
上の例ではread用のcharacteristicを含むserviceを定義しています。

Advertiseの実装

Advertiseは Android-BLE-Library の範囲外なので自分で実装する必要があります。


class SampleBleServerManager(private val context: Context) 
    : BleServerManager(context) {
    
    // 追加
    fun startAdvertising() {
        val adviserSettings = AdvertiseSettings.Builder()
            .build()
        val advertiseData = AdvertiseData.Builder()
            .addServiceUuid(ParcelUuid(serviceUuid))
            .build()
        val advertiseCallback = object : AdvertiseCallback() {}

        //  Advertise開始
        BluetoothAdapter.getDefaultAdapter().bluetoothLeAdvertiser
            ?.startAdvertising(adviserSettings, advertiseData, advertiseCallback)
    }
}

BleManager の継承

次にCentralとの接続から切断までを制御するために BleManager を継承したclassを実装します。
BleManager Centralの実装時にも登場しましたが、Peripheralを実装するときも使用します。


class SampleConnectedBleManager(context: Context) 
    : BleManager(context) {

    private var gattCallback: BleManagerGattCallback? = null
    private inner class GattCallback : BleManagerGattCallback() {
        override fun isRequiredServiceSupported(gatt: BluetoothGatt) = true
        override fun onDeviceDisconnected() {}
    }

    override fun getGattCallback() = gattCallback ?: run {
        gattCallback = GattCallback()
        gattCallback!!
    }
}


BLE接続された時

最後に BleServerManager に接続された時に BleManager を関連づけます。


class SampleBleServerManager(private val context: Context)
    : BleServerManager(context) {
    
    private val connectionObserver = object: BaseConnectionObserver {}
    private val serverObserver = object: ServerObserver {
        override fun onServerReady() {
            // advertise開始
            startAdvertising()
        }

        override fun onDeviceConnectedToServer(device: BluetoothDevice) {
            //  BleServerManager と BleManager を関連づける
            val connectedManager = SampleConnectedBleManager(context)
            connectedManager. setConnectionObserver(connectionObserver)
            connectedManager.useServer(this)

            connectedManager
                .connect(device)
                .enqueue()
        }

        override fun onDeviceDisconnectedFromServer(device: BluetoothDevice) {}
    }

    init {
        setServerObserver(serverObserver)
    }
}


SampleBleServerManager#open() をコールすると SampleBleServerManager#initializeServer() が実行され、Peripheralとしての動作準備を行います。
動作準備が完了すると SampleBleServerManager#onServerReady() がコールされるので、Advertiseを開始してPeripheralとして動作します。


val bleServerManager = SampleBleServerManager(context)
bleServerManager.open()


メリット

Peripheralを実装するには接続したCentralのBluetoothDeviceインスタンスを管理する必要がありますが、BleServerManager を利用するとその必要もありません。
またCentralとのコミュニケーションを BleManager が行うので、リクエスト・レスポンスのキューを実装する必要がありません。

AndroidのBLE処理をきちんと実装するとコード量が多くなりがちですが、Android-BLE-Libraryを利用すると結構コンパクトに実装できます。

サンプルアプリを含めたソースコード全体は github で確認できます。

SNS SHARE