Reputation: 25060
I'm trying to read the initial state of a BLE device when I connect to it. Here's the code I have to try to do that:
@Override
public void onServicesDiscovered(BluetoothGatt gatt, int status)
{
if(status == BluetoothGatt.GATT_SUCCESS)
{
Log.i(TAG, gatt.getDevice().toString() + "Discovered Service Status: " + gattStatusToString(status));
for(BluetoothGattService service : gatt.getServices())
{
Log.i(TAG, "Discovered Service: " + service.getUuid().toString() + " with " + "characteristics:");
for(BluetoothGattCharacteristic characteristic : service.getCharacteristics())
{
// Set notifiable
if(!gatt.setCharacteristicNotification(characteristic, true))
{
Log.e(TAG, "Failed to set notification for: " + characteristic.toString());
}
// Enable notification descriptor
BluetoothGattDescriptor descriptor = characteristic.getDescriptor(CCC_UUID);
if(descriptor != null)
{
descriptor.setValue(BluetoothGattDescriptor.ENABLE_NOTIFICATION_VALUE);
gatt.writeDescriptor(descriptor);
}
// Read characteristic
if(!gatt.readCharacteristic(characteristic))
{
Log.e(TAG, "Failed to read characteristic: " + characteristic.toString());
}
}
}
}
else
{
Log.d(TAG, "Discover Services status: " + gattStatusToString(status));
}
}
But the read fails every time! Later if I initiate a read based on UI interaction it reads just fine! Any ideas about what's going on here?
Upvotes: 6
Views: 10876
Reputation: 3694
In the Android BLE implementation, the gatt operation calls need to be queued so that only one operation (read, write, etc.) is in effect at a time. So for example, after gatt.readCharacteristic(characteristicX)
is called, you need to wait for the gatt callbackBluetoothGattCallback.onCharacteristicRead()
to indicate the read is finished. If you initiate a second gatt.readCharacteristic() operation before the previous one completes, the second one will fail (by returning false) This goes for all of the gatt.XXX() operations.
Its a little work, but I think the best solution is to create a command queue for all the gatt operations and run them one at a time. You can use the command pattern to accomplish this.
Upvotes: 16