I have a message thread for sending a buffer of messages. Each message is queued to be sent once onCharacteristicWrite
is successful before the characteristic writes the next message. The characeristic is also set to WRITE_TYPE_NO_RESPONSE
, so the message buffer queue is pretty fast (0-7ms approximately) between characteristic write calls.
The main issue: "jammed up" characteristic
For the most part this works great. The problem seems to arise when there's a large amount of messages (possibly happens with fewer message, but is more noticeable when sending lots of messages). What happens is writeCharacteristic
will get called, and the characteristic seems to lock up, since onCharacteristicChanged
no longer reads any new data, and doesn't get to onCharacteristicWrite
.
Other things I've noticed:
Adding a sleep delay of 5-10ms after each
characteristicWrite
seems to help, but I don't understand why the Bluetooth GATT object would need a delay whenonCharacteristicWrite
returns successful.Sometimes I'll get a callback in
onConnectionStateChange
with status 8, device out of range. This doesn't always happen though.- Sometimes
characteristicWrite
returns false; however, it can also return true before going into the "jammed up characteristic" state described above
Message Thread code:
private boolean stopMessageThread = false;
private boolean characteristicWriteSuccessful = true;
private ArrayList<byte[]> messageQueue = new ArrayList<byte[]>();
private Thread messageThread = new Thread( new Runnable() {
private long lastTime = 0;
private int count = 0;
@Override
public void run() {
while (!Thread.currentThread().isInterrupted() && !stopMessageThread) {
if(messageQueue.size() != 0 && characteristicWriteSuccessful) {
Log.i(TAG, ""+(System.currentTimeMillis()-lastTime));
Log.i(TAG, "Queue count: "+messageQueue.size());
characteristicWriteSuccessful = false;
byte[] message = messageQueue.remove(0);
customCharacteristic.setValue(message);
boolean status = bluetoothGatt.writeCharacteristic(customCharacteristic);
Log.i(TAG, "write characteristic status "+status);
lastTime = System.currentTimeMillis();
//sleep(10); // this kinda helps but can still throw the error
}
}
}
});