I am attempting to subscribe to multiple characteristics of a BLE peripheral within Android API 28.
Due to the asynchronous nature of the BLE API I need to make the function that subscribes to each characteristic (gatt.writeDescriptor()
) block; otherwise the BLE API will attempt to subscribe to multiple characteristics at once, despite the fact that only one descriptor can be written at a time: meaning that only one characteristic is ever subscribed to.
The blocking is achieved by overriding the onServicesDiscovered
callback and calling an asynchronous function to loop through and subscribe to characteristics. This is blocked with a simple Boolean value (canContinue
). Unfortunately, the callback function onDescriptorWrite
is never called.
See the code below:
override fun onDescriptorWrite(gatt: BluetoothGatt, descriptor: BluetoothGattDescriptor, status: Int) {
canContinue = true
}
override fun onServicesDiscovered(gatt: BluetoothGatt, status: Int) {
runBlocking {
loopAsync(gatt)
}
}
private suspend fun loopAsync(gatt: BluetoothGatt) {
coroutineScope {
async {
gatt.services.forEach { gattService ->
gattService.characteristics.forEach { gattChar ->
CHAR_LIST.forEach {
if (gattChar.uuid.toString().contains(it)) {
canContinue = false
gatt.setCharacteristicNotification(gattChar, true)
val descriptor = gattChar.getDescriptor(UUID.fromString(BleNamesResolver.CLIENT_CHARACTERISTIC_CONFIG))
descriptor.value = BluetoothGattDescriptor.ENABLE_NOTIFICATION_VALUE
val write = Runnable {
gatt.writeDescriptor(descriptor)
}
//private val mainHandler = Handler(Looper.getMainLooper())
//mainHandler.post(write)
//runOnUiThread(write)
gatt.writeDescriptor(descriptor)
}
while (!canContinue)
}
}
}
}
}
}
It was suggested in a related post that I run the gatt.writeDescriptor()
function in the main thread. As you can see in the code above I have tried this to no avail using both runOnUiThread()
and creating a Handler object following suggestions from this question.
The callback gets called if I call gatt.writeDescriptor()
from a synchronous function, I have no idea why it doesn't get called from an asynchronous function.
EDIT: It appears that the while(!canContinue);
loop is actually blocking the callback. If I comment this line out, the callback triggers but then I face the same issue as before. How can I block this function?
Any suggestions are most welcome! Forgive my ignorance, but I am very much used to working on embedded systems, Android is very much a new world to me!
Thanks, Adam