Home » Android » bluetooth lowenergy – Android BLE BluetoothGatt.writeDescriptor() return sometimes false

bluetooth lowenergy – Android BLE BluetoothGatt.writeDescriptor() return sometimes false

Posted by: admin June 15, 2020 Leave a comment


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 writeCharacteristic()?
  • Also if there is inter-function dependency then what else function have this limitation (namely: readCharacteristic(), readDescriptor(), requestMtu()…)?
  • And additionally is there interdependency between BluetoothGattServer and BluetoothGatt. So for example when I call BluetoothGattServer.notifyCharacteristicChanged() shall I wait forBluetoothGattServerCallback.onNotificationSent before I can call BluetoothGatt.writeDescriptor() or 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.
How to&Answers:

The documentation lacks information. However you can read the source code to find out the rules, which (currently) are the following:

For each BluetoothGatt object, you can only have one outstanding request at a time, including requestMtu, readCharacteristic, writeCharacteristic, readDescriptor, writeDescriptor and 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.