Device used for testing: Nexus 4, Android 4.3
Connection is working fine but the onCharacteristicChangedMethod of my callback is never called. However I
@Boni2k - I have the same issues. In my case, I have 3 notifying characteristics and a handful of read/write characteristics.
What I did find is that there is some dependency between writeGattDescriptor and readCharacteristic. All of the writeGattDescriptors must come first and complete before you issue any readCharacteristic calls.
Here is my solution using Queues. Now I am getting notifications and everything else works fine:
Create two Queues like this:
private Queue descriptorWriteQueue = new LinkedList();
private Queue characteristicReadQueue = new LinkedList();
Then write all of your descriptors immediately after discovery with this method:
public void writeGattDescriptor(BluetoothGattDescriptor d){
//put the descriptor into the write queue
descriptorWriteQueue.add(d);
//if there is only 1 item in the queue, then write it. If more than 1, we handle asynchronously in the callback above
if(descriptorWriteQueue.size() == 1){
mBluetoothGatt.writeDescriptor(d);
}
}
and this callback:
public void onDescriptorWrite(BluetoothGatt gatt, BluetoothGattDescriptor descriptor, int status) {
if (status == BluetoothGatt.GATT_SUCCESS) {
Log.d(TAG, "Callback: Wrote GATT Descriptor successfully.");
}
else{
Log.d(TAG, "Callback: Error writing GATT Descriptor: "+ status);
}
descriptorWriteQueue.remove(); //pop the item that we just finishing writing
//if there is more to write, do it!
if(descriptorWriteQueue.size() > 0)
mBluetoothGatt.writeDescriptor(descriptorWriteQueue.element());
else if(readCharacteristicQueue.size() > 0)
mBluetoothGatt.readCharacteristic(readQueue.element());
};
The method for reading a characteristic normally then looks like this:
public void readCharacteristic(String characteristicName) {
if (mBluetoothAdapter == null || mBluetoothGatt == null) {
Log.w(TAG, "BluetoothAdapter not initialized");
return;
}
BluetoothGattService s = mBluetoothGatt.getService(UUID.fromString(kYourServiceUUIDString));
BluetoothGattCharacteristic c = s.getCharacteristic(UUID.fromString(characteristicName));
//put the characteristic into the read queue
readCharacteristicQueue.add(c);
//if there is only 1 item in the queue, then read it. If more than 1, we handle asynchronously in the callback above
//GIVE PRECEDENCE to descriptor writes. They must all finish first.
if((readCharacteristicQueue.size() == 1) && (descriptorWriteQueue.size() == 0))
mBluetoothGatt.readCharacteristic(c);
}
and my read callback:
public void onCharacteristicRead(BluetoothGatt gatt,
BluetoothGattCharacteristic characteristic,
int status) {
readCharacteristicQueue.remove();
if (status == BluetoothGatt.GATT_SUCCESS) {
broadcastUpdate(ACTION_DATA_AVAILABLE, characteristic);
}
else{
Log.d(TAG, "onCharacteristicRead error: " + status);
}
if(readCharacteristicQueue.size() > 0)
mBluetoothGatt.readCharacteristic(readCharacteristicQueue.element());
}