Android BLE: onCharacteristicRead() blockiert zu sein scheint, durch den thread
Ich bin Umsetzung einer Reihe von charakteristischen liest gegen eine BLE-Gerät. Da readCharacteristic()
wird asynchron ausgeführt, und da müssen wir warten, bis es abgeschlossen ist, bevor Sie die Ausstellung von einem anderen "Lesen" nennen, habe ich eine Sperre zu wait()
und dann in 'onCharacteristicRead()
ich notify()
die Sperre, um die Dinge wieder in Gang.
Wenn ich wait()
nach dem Aufruf readCharacteristic()
ich nie einen Anruf erhalten zu onCharacteristicRead()
. Wenn ich nicht wait()
, dann bekomme ich ein Anruf, um onCharacteristicRead()
und der richtige Wert wird berichtet.
Hier ist der entsprechende code, der scheint zu blockieren, den Rückruf onCharacteristicRead()
:
private void doRead() {
//....internal accounting stuff up here....
characteristic = mGatt.getService(mCurrServiceUUID).getCharacteristic(mCurrCharacteristicUUID);
isReading = mGatt.readCharacteristic(characteristic);
showToast("Is reading in progress? " + isReading);
showToast("On thread: " + Thread.currentThread().getName());
//Wait for read to complete before continuing.
while (isReading) {
synchronized (readLock) {
try {
readLock.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
public void onCharacteristicRead(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic, int status) {
showToast("onCharacteristicRead()");
showToast("On thread: " + Thread.currentThread().getName());
byte[] value = characteristic.getValue();
StringBuilder sb = new StringBuilder();
for (byte b : value) {
sb.append(String.format("%02X", b));
}
showToast("Read characteristic value: " + sb.toString());
synchronized (readLock) {
isReading = false;
readLock.notifyAll();
}
}
Wenn ich entfernen Sie einfach den while()
Aussage oben, habe ich erfolgreich die lese-callback. Natürlich hindert mich, warten, um Sie dann weiter liest, so kann ich mich nicht bewegen vorwärts ohne zu warten.
Gegeben, dass die readCharacteristic()
asynchron ist, warum würde die Ausführung des aufrufenden Threads haben nichts zu tun mit der Fähigkeit, tatsächlich das zu Lesen, oder die Möglichkeit zum Aufruf der callback?
Um die Dinge eher verwirrend, zeige ich einen toast, identifiziert den thread, wenn ich rufe readCharacteristic()
sowie bei onCharacteristicRead()
aufgerufen. Diese 2 threads verschiedene Namen haben. Ich dachte, dass vielleicht der Rückruf wurde aufgerufen, auf den aufrufenden thread aus irgendeinem Grund, aber das scheint nicht der Fall zu sein. Also, was ist hier Los mit dem Gewinde?
Du musst angemeldet sein, um einen Kommentar abzugeben.
Das problem hier scheint zu sein, ein ungeklärtes Problem mit dem Durchzug, und es kann nicht gesehen werden, in meinem original-post, weil ich nicht post reicht der Anruf-Historie zu sehen. Ich werde erklären, was ich hier gefunden, falls es Effekte jemand anderes.
Den vollständigen call Geschichte was zu meinem problem ging so etwas wie dieses:
discoverServices()
onServicesDiscovered()
doRead()
Methode in meinem ursprünglichen postreadCharacteristic()
---- Dies ist, wo deadlock Auftritt, aber sein soll:
onCharacteristicRead()
Erste Fehler:
Ursprünglich meine
onServicesDiscovered()
Methode sah so aus:Wenn
doRead()
führt, es ist zu gehen zu schlafen und blockieren deshalb die Ausführung. Dies verhindert, dass die callback-Methode von finishing-und offenbar gunks die gesamte BLE communicaiton system.Zweite Fehler:
Einmal merkte ich das oben genannte Problem, ich habe die Methode, die der folgenden:
Soweit ich das beurteilen kann, die oben genannten version der Methode sollte funktionieren. Ich erstelle einen neuen thread für die Ausführung von
doRead()
, so schläft indoRead()
sollten keine Auswirkungen auf die BLE-thread. Aber es funktioniert! Diese änderung hatte keine Auswirkungen.----------- Notiz Bearbeiten --------------
Nachdem dieses posting, ich konnte es nicht wirklich begründen, warum die genannten anonymen thread nicht funktionieren würde. Also versuchte ich es erneut, und dieses mal ist es funktionierte. Nicht sicher, was schief gelaufen das erste mal, vielleicht habe ich vergessen zu nennen
start()
auf den thread oder so...--------- Ende Notiz Bearbeiten ------------
Die Lösung:
Schließlich aus einer Laune heraus, entschied ich mich für einen hintergrund
HandlerThread
wenn meine Klasse instanziiert (statt spinning eine anonymeThread
imonServicesDiscovered()
). Die Methode sieht nun wie folgt aus:Die obige version funktioniert die Methode. Der Aufruf
doRead()
erfolgreich durchläuft jedes Merkmal als das Vorherige Lesen.mBackgroundHandler
bekommen initialisiert?Ich dieses problem gelöst haben, indem Sie den folgenden code