0

I've initiated a BLE connection, in onServicesDiscovered I'm going to read out all descriptors. There are five of them and I proceed with this:

for (int n=0;n<descriptors.size();n++)
{
     gatt.readDescriptor(descriptors.get(n));
}

descriptors contains all descriptors... Then the read callback is called and I'm going to read out the descriptors value:

@Override
public void onDescriptorRead(BluetoothGatt gatt, final BluetoothGattDescriptor descriptor, int status)
{
     deviceInfoArray.add(new ItemSlideMenu(new String(descriptor.getValue()));
}

The problem is, that the read callback is only called once, instead of five times. Can you tell me why and how to fix this?

2 Answers2

2

You can only have one outstanding gatt operation at a time. You must wait until the corresponding callback has been fired until you can do a new read. A good way to solve this is to have a queue data structure. When you want to do a read/write, insert an operation into this queue. Whenever you insert an operation and the queue was already empty OR you get a callback telling some operation is done, then issue the next operation in the queue. Remove the operation from the queue when the gatt callback arrives. That way you can be sure only one operation will be outstanding at a time.

You can also attach a Runnable to an operation which should be called when the gatt callback arrives.

Emil
  • 16,784
  • 2
  • 41
  • 52
  • Is there a way to check if a gatt Operation is running? I want to Queue them all together, but I'm not sure which one is running on time. – Luis Garcia Feb 10 '17 at 07:02
  • There is no way in the API to check that. You must do it yourself in a thread safe manner – Emil Feb 10 '17 at 09:17
  • Hm.. I have written down all operations and check them now manually. Works great! – Luis Garcia Feb 10 '17 at 09:19
0

That's a great idea, thank you! Especially when you have different GATT operations. Nevertheless I solved it this way:

@Override
public void onDescriptorRead(BluetoothGatt gatt, final BluetoothGattDescriptor descriptor, int status)
    {
        deviceInfoArray.add(new ItemSlideMenu(new String(descriptor.getValue()), descriptor.getCharacteristic()));
        //Call this to update the adapter of deviceInfoList
        getActivity().runOnUiThread(updateAdapter);
        Log.d("xxx", new String(descriptor.getValue()));

        if(descriptors.size() > 1)
        {
            BluetoothGattDescriptor tempDescriptor = descriptors.get(1);
            descriptors.remove(1);
            mGatt.readDescriptor(tempDescriptor);
        }
    }

onDescriptorRead is called recursive and terminates itselfs.