![](/img/trans.png)
[英]Using Kotlin Coroutines to replace LocalBroadcastManager for Firebase messaging
[英]Replace BLE callbacks using Kotlin Coroutines
我想使用 Kotlin 的協程來處理 BLE 的異步回調。 連接到 BLE 設備需要回調 object,類似於:
connectToBle(Context, Boolean, GattCallback)
結果在 GattCallback object 的onConnectionStateChanged
方法中異步返回。我使用suspendCoroutine<BluetoothGatt>
來實現它,詳見此處的文檔。
現在onConnectionStateChanged
返回一個 BluetoothGatt object ,我必須將其保存為全局變量並用於調用其他方法,例如discoverServices
、 readCharacteristic
、 writeCharacteristic
等,所有這些方法都在 GattCallback object 的不同回調方法中異步返回,例如onServicesDiscovered
、 onCharacteristicRead
, onCharacteristicWrite
等等。
這是使用suspendCoroutine
的代碼:
suspend fun BluetoothDevice.connectToBleDevice(
context: Context,
autoConnect: Boolean = false
) = suspendCoroutine<BluetoothGatt?> { cont ->
connectGatt(context, autoConnect, object : BluetoothGattCallback() {
override fun onConnectionStateChange(gatt: BluetoothGatt?, status: Int, newState: Int) {
super.onConnectionStateChange(gatt, status, newState)
Timber.d("onConnectionStateChange: ")
if (status != BluetoothGatt.GATT_SUCCESS) cont.resume(null) else cont.resume(gatt)
// save gatt instance here if success
}
override fun onServicesDiscovered(gatt: BluetoothGatt?, status: Int) {
super.onServicesDiscovered(gatt, status)
if (status != BluetoothGatt.GATT_SUCCESS) cont.resume(null) else cont.resume(gatt)
// return list of services if success
}
override fun onCharacteristicRead(
gatt: BluetoothGatt?,
characteristic: BluetoothGattCharacteristic?,
status: Int
) {
super.onCharacteristicRead(gatt, characteristic, status)
if (status != BluetoothGatt.GATT_SUCCESS) cont.resume(null) else cont.resume(gatt)
// return read value if success
}
})
}
在保存的 gatt 實例上調用的方法:
fun discoverServices() {
gatt?.discoverServices() // result received in onServicesDiscovered
}
fun readCharacteristic(serviceUUID: UUID, characteristicUUID: UUID) {
gatt?.apply {
val characteristic =
getService(serviceUUID).getCharacteristic(characteristicUUID)
readCharacteristic(characteristic) // result received in onCharacteristicRead
}
}
如果我想編寫如下“順序代碼”:
val gatt = connectToBle(context, false, gattCallback) // suspend until onConnectionStateChanged returns successfully
discoverServices() // suspend until discoverServices returns successfully
writeCharacteristic(characteristic, valueToWrite) // suspend until value is written successfully
val valueRead = readCharacteristic(characteristic) // suspend until the value is read successfully
disconnect()
我必須做出哪些改變? 我應該使用 suspendCoroutine 以外的東西嗎?
聽起來Kable可能符合您的需求? 它提供了一個 API 類似於您所描述的。
例如,您可以使用以下代碼連接、寫入/讀取特征,然后斷開連接:
val characteristic = characteristicOf(
service = "00001815-0000-1000-8000-00805f9b34fb",
characteristic = "00002a56-0000-1000-8000-00805f9b34fb"
)
// todo: Use scanner (provided by Kable) to obtain `peripheral`.
peripheral.apply {
connect()
write(characteristic, byteArrayOf(1, 2, 3))
val valueRead: ByteArray = read(characteristic)
disconnect()
}
免責聲明:我是Kable的貢獻者,所以這是一個有偏見的自我插件。 ♂️
如果有人仍在尋找答案,則可以使用協程通道(或者也可以使用 callbackFlow)來實現
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.