I’m trying to write BLE Android app. I found that sometimes when I call
BluetoothGatt.writeDescriptor() it returns false.
I have not found in documentation any note of limitation to this function. But ppl on stack overflow says that I need to wait for BluetoothGattCallback.onDescriptorWrite() before I try to write another descriptor.
Here is one reply saying that BLE is busy with writeDescriptor() and can not do other write.
Here is another thread saying that you can not call twice writeCharacteristic().
My questions are
- is it really true?
- is there really missing some internal android API buffer for serializing BLE requests and every developer has to do it on it’s own?
- Is it true for different functions? For example when I call
writeDescriptor()I understand I can not call second time
writeDescriptor()before I receive
onDescriptorWrite(). But do I have to wait for
onDescriptorWrite()when I want to call
- Also if there is inter-function dependency then what else function have this limitation (namely:
- And additionally is there interdependency between BluetoothGattServer and BluetoothGatt. So for example when I call
BluetoothGattServer.notifyCharacteristicChanged()shall I wait for
BluetoothGattServerCallback.onNotificationSentbefore I can call
BluetoothGatt.writeCharacteristic()? (BTW praise for google documentation
onNotificationSent()is by luck documented properly. Doc says:
When multiple notifications are to be sent, an application must wait
for this callback to be received before sending additional
- Lastly having all this questions – I feel that Android BLE API is under-documented. Or am I wrong and there is documented somewhere what are allowed methods calling sequences? If yes can you please point me to such documentation? If not is there some channel we can open issue with google and ask them to add to documentation something? I mean it may not be much text – some function like
onNotificationSent()is arleady properly documented. They just need to copy this sentence to other functions.
The documentation lacks information. However you can read the source code to find out the rules, which (currently) are the following:
BluetoothGatt object, you can only have one outstanding request at a time, including
executeReliableWrite. So if you issue a read request you need to wait for the read response before you issue a write request. While they implemented the code that returns false if there is an ongoing operation in BluetoothGatt.java, they forgot to do this for
requestMtu, so if you have multiple requests at a time where
requestMtu is one of them, you will get random errors sooner or later (in the latest versions at the time of this post).
So yes, every developer has to manually serialize the requests. Note that the Bluetooth stack actually has a queue of requests, but it is limited to only one request per client (i.e. BluetoothGatt object). So if two apps on the same phone talk to the same device simultaneously you will never get “busy” errors. The only exception is if you use Write Without Response for which the current data flow implementation is quite buggy (see https://issuetracker.google.com/issues/37121017 which Google seems to have ignored).
You can send notifications at the same time as you write a characteristic, since the server and client roles are separated.
Regarding updating the documentation, you can always try to file an issue at https://issuetracker.google.com (but I get the feeling nobody reads that), or, since Android is open source, send a pull request to https://android-review.googlesource.com/ which updates the Javadoc from which the documentation is generated.