Android BLE readCharacteristic fails
Asked Answered
M

1

6

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?

Medora answered 22/5, 2015 at 13:55 Comment(3)
Maybe you need to pair/bond before reading?Jaquez
When the BLE signal strength (RSSI value) is low, it may cause a failure of the discover service or result in an unpredictable broken connection. Checking your RSSI value would help here.Torquemada
May i ask you some question; Where is CCC_UUID you take from ? Should we enable descriptor notify ?Emersen
M
15

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.

Mog answered 8/6, 2015 at 22:39 Comment(3)
One question : also for onCharacteristicChanged I have to implement command pattern ?Pretender
No. There is no command/response pattern for notifiable characteristics. The notifications (onCharacteristicChanged) come in asynchronously and should not affect, nor be affected by, the command queueing for other reads and writes.Mog
I do not have direct experience interacting with a device using all the API's so I can't be completely sure what they all do. But a number of them return booleans to "indicate if the command was successfully initiated". The docs don't say this, but I suspect that most of them will fail if the BluetoothGatt is currently processing a read or write. That is a read or write has been initiated, but the corresponding BluetoothGattCallback hasn't been received. With that said, I would guess that if you call SetCharacteristicNotification while a read or write is in progress it will fail.Mog

© 2022 - 2024 — McMap. All rights reserved.