Android 4.3 Bluetooth Low Energy instabil

189

Ich entwickle derzeit eine Anwendung, die Bluetooth Low Energy verwendet (Test auf dem Nexus 4). Nachdem ich mit den offiziellen BLE-APIs in Android 4.3 begonnen habe, habe ich festgestellt, dass ich nach dem ersten Anschließen eines Geräts selten wieder erfolgreich eine Verbindung zu diesem Gerät oder einem anderen Gerät herstellen / mit ihm kommunizieren kann.

Wenn ich der Anleitung hier folge , kann ich ohne Probleme erfolgreich eine Verbindung zu einem Gerät herstellen, Dienste und Eigenschaften scannen und Benachrichtigungen lesen / schreiben / empfangen. Nach dem Trennen und erneuten Verbinden kann ich jedoch häufig weder Dienste / Merkmale scannen noch Lese- / Schreibvorgänge ausführen. Ich kann in den Protokollen nichts finden, was darauf hinweist, warum dies geschieht.

In diesem Fall muss ich die Anwendung deinstallieren, Bluetooth deaktivieren und das Telefon neu starten, bevor es wieder funktioniert.

Immer wenn ein Gerät getrennt wird, rufe ich close () für das BluetoothGatt-Objekt auf und setze es auf null. Irgendwelche Einsichten?


BEARBEITEN:
Protokollspeicherauszüge: Für diese Protokolle habe ich mein Telefon gerootet und die Ablaufverfolgungsstufen verwandter Elemente in /etc/bluetooth/bt_stack.conf erhöht

Erfolgreiche Verbindung - Erster Versuch nach dem Neustart des Telefons und der Installation der App. Ich kann eine Verbindung herstellen, alle Dienste / Merkmale entdecken und lesen / schreiben.

Fehlgeschlagener Versuch 1 - Dies ist der nächste Versuch nach dem Trennen von der oben genannten erfolgreichen Verbindung. Es scheint, dass ich Merkmale entdecken konnte, aber der erste Leseversuch ergab einen Nullwert und wurde bald darauf getrennt.

Fehlgeschlagener Versuch 2 - Ein Beispiel, bei dem ich nicht einmal Dienste / Merkmale erkennen kann.


EDIT 2:
Das Gerät, mit dem ich eine Verbindung herstellen möchte, basiert auf dem CC2541-Chip von TI. Ich habe einen TI SensorTag (ebenfalls basierend auf dem CC2541) zum Herumspielen erhalten und festgestellt, dass TI gestern eine Android-App für den SensorTag veröffentlicht hat. Diese App hat jedoch das gleiche Problem. Ich habe dies auf zwei anderen Nexus 4 mit dem gleichen Ergebnis getestet: Die Verbindung zum SensorTag ist beim ersten oder zweiten Mal erfolgreich, aber (laut Protokoll) kann ich danach keine Dienste mehr erkennen, was zu allen möglichen Abstürzen führt. Ich frage mich, ob es ein Problem mit diesem speziellen Chip ist.

sa.shadow
quelle
Bitte veröffentlichen Sie vollständige Protokolle Ihres Telefons vom Start bis zum Auftreten des Problems.
AAnkit
3
Ich verwende Samsung Galaxy S4 mit durchgesickerter Google Edition Android 4.3. Nach mehrmaligem Verbinden / Trennen erhalte ich beim Erkennen von Diensten nach dem Zufallsprinzip 129 (GATT_INTERNAL_ERROR) und einen onConnectionStateChange mit dem Status 133 (GATT_ERROR), state = BluetoothProfile.DEVICE_DISCONNECTED.
reTs
1
Ein- oder zweimal erhielt ich in kurzer Zeit mehrere Rückrufe mit Status 129 und 133 und konnte in BluetoothGattCallback keinen Rückruf erhalten, bis ich mein Gerät neu startete (aber das Scannen ist in Ordnung).
reTs
1
Vergessen Sie zu sagen, dass ich mit ungefähr zehn Geräten mit TI-Chips (leider kenne ich ihre Modelle nicht) und einem Gerät mit nordischen Chips teste. Das Gerät mit nordischen Chips meldet niemals einen Fehler (nicht genug, um zu beweisen, dass das Problem TI-spezifisch ist)
reTs
1
Ich kann bestätigen, dass dieses Problem auf dem Samsung Galaxy S5 ( Build-Version G900VVRU2BOG5 und G900VVRU2BOA8 ) weiterhin besteht. Wenn ich Daten über Einstellungen> Anwendungsmanager >> Alle >> Bluetooth lösche , funktioniert dies vorerst.
IronBlossom

Antworten:

184

Wichtige Implementierungshinweise

(Möglicherweise sind einige dieser Hinweise aufgrund von Android-Betriebssystem-Updates nicht mehr erforderlich.)

  1. Einige Geräte wie Nexus 4 mit Android 4.3 benötigen mehr als 45 Sekunden, um eine Verbindung mit einer vorhandenen Gatt-Instanz herzustellen . Umgehen: Schließen Sie Gatt-Instanzen immer beim Trennen und erstellen Sie bei jeder Verbindung eine neue Gatt-Instanz.
  2. Vergiss nicht anzurufen android.bluetooth.BluetoothGatt#close()
  3. Starten Sie einen neuen Thread im Inneren onLeScan(..) und verbinden Sie sich dann. Grund: BluetoothDevice#connectGatt(Context context, boolean autoConnect, BluetoothGattCallback callback)schlägt immer fehl, wenn LeScanCallback() {...}.onLeScan(BluetoothDevice device, int rssi, byte[] scanRecord)im selben Thread auf Samsung Galaxy S3 mit Android 4.3 (zumindest für Build JSS15J.I9300XXUGMK6) aufgerufen wird.
  4. Die meisten Geräte filtern Werbung
  5. Verwenden Sie android.bluetooth.BluetoothAdapter#startLeScan(UUID[] serviceUuids, LeScanCallback callback) den Parameter besser nicht , um nach bestimmten Dienst-UUIDs zu filtern, da dies in Samsung Galaxy S3 mit Android 4.3 vollständig fehlerhaft ist und für 128-Bit-UUIDs im Allgemeinen nicht funktioniert .
  6. Gatt kann immer jeweils einen Befehl verarbeiten . Wenn mehrere Befehle kurz nacheinander aufgerufen werden, wird der erste aufgrund der Synchronität der Gatt-Implementierung abgebrochen .
  7. Selbst auf modernen Geräten mit Android 5 sehe ich oft, dass Wifi Bluetooth stört und umgekehrt. Schalten Sie als letzten Ausweg das WLAN aus, um Bluetooth zu stabilisieren.

Tutorial für Anfänger

Ein ziemlich guter Einstiegspunkt für Neulinge könnte dieses Video-Tutorial sein: Entwickeln von Bluetooth Smart-Anwendungen für Android http://youtu.be/x1y4tEHDwk0

Das unten beschriebene Problem und die Problemumgehung werden jetzt wahrscheinlich durch Betriebssystemupdates behoben

Umgehen: Ich könnte meine App damit "stabilisieren" ...

  1. Ich gebe dem Benutzer die Einstellung "Bluetooth neu starten". Wenn diese Einstellung aktiviert ist, starte ich Bluetooth an einigen Stellen neu, die darauf hinweisen, dass der Beginn des BLE-Stacks instabil wird. Beispiel, wenn startScan false zurückgibt. Ein guter Punkt kann auch sein, wenn serviceDiscovery fehlschlägt. Ich schalte Bluetooth einfach aus und wieder ein.
  2. Ich biete eine andere Einstellung "WiFi ausschalten". Wenn diese Einstellung aktiviert ist, deaktiviert meine App Wifi, wenn die App ausgeführt wird (und schaltet sie anschließend wieder ein).

Diese Problemumgehung basiert auf folgenden Erfahrungen ...

  • Durch einen Neustart von Bluetooth können in den meisten Fällen Probleme mit BLE behoben werden
  • Wenn Sie Wifi ausschalten, wird der BLE-Stapel viel stabiler. Es funktioniert jedoch auch auf den meisten Geräten mit aktiviertem WLAN einwandfrei.
  • Wenn Sie Wifi deaktivieren, wird durch einen Neustart von Bluetooth der BLE-Stack vollständig wiederhergestellt, ohne dass das Gerät in den meisten Fällen neu gestartet werden muss.
Eine Welt
quelle
33
Google, du musst das jetzt beheben. Diese Umgehung (ich habe es getan, weil es funktioniert) ist lächerlich.
Chris Herbert
4
Manchmal ist die Serviceerkennung mit dem Status 0 erfolgreich (vorausgesetzt, keine Probleme), aber das Lesen von Merkmalen ergibt NULL-Werte, da es im Wesentlichen nicht wirklich verbunden ist oder die Merkmale nicht entdeckt wurden (ich sehe dies im Protokoll: 11-01 18:37: 32.131: WARN / BluetoothGatt (20119): Nicht behandelte Ausnahme: java.lang.NullPointerException)
Lo-Tan
2
@ Lo-Tan Ich überprüfe immer nach der Serviceerkennung, ob mein erwarteter Service enthalten ist. Sie können auch nie sicher sein, ob die Serviceerkennung ein Ergebnis liefert. Manchmal erhalte ich keinen Rückruf. Also habe ich eine Zeitüberschreitung für die Serviceerkennung angewendet.
OneWorld
2
Meine Erfahrung ist: Samsung S3 (4.3) wurde nach dem Schließen eines Gatt-Clients wie in Absatz 2 oben beschrieben erfolgreich wieder verbunden; mit Nexus 4 & 7 (4.4.2) Ich konnte die Verbindung nach dem Verbindungsabbruch nicht wiederherstellen, selbst wenn der BL-Adapter neu gestartet wurde, aber sie kann nach 2 Minuten automatisch wieder verbunden werden
Konstantin Konopko
1
Kann jemand bestätigen , wenn android.bluetooth.BluetoothGatt kann man anhängige GATT Betrieb nur behandeln pro Gerät , pro Prozess oder PERIODE (: über alle Prozesse hinweg dh). Ich nehme an, es ist PER DEVICE, aber dieses Problem ist so durcheinander, dass es mich nicht überraschen würde, wenn es anders wäre. Wenn die Einschränkung nur PRO GERÄT ist, ist das Betriebssystem / Gerät, das mehrere gleichzeitige Vorgänge ausführen kann, ein Beweis dafür, dass dieses Problem ausschließlich auf eine schwache naive Implementierung in der BluetoothAdapter-Instanz zurückzuführen ist, die das Betriebssystem für jeden Prozess bereitstellt (was ich angenommen hatte) ein Singleton über alle Prozesse hinweg).
Swooby
18

WIFI ausschalten:

Ich kann auch bestätigen, dass durch das Ausschalten von WIFI Bluetooth 4.0 insbesondere unter Google Nexus (ich habe ein Nexus 7) stabiler wird.

Das Problem

ist , dass die Anwendung , die ich entwickeln werde muss sowohl WIFI und kontinuierliche Bluetooth LE - Scanning . Das Ausschalten von WIFI war für mich also keine Option.

Außerdem habe ich festgestellt, dass ein kontinuierliches Bluetooth LE-Scannen die WIFI-Verbindung tatsächlich beenden und den WIFI-Adapter dazu bringen kann, keine Verbindung zu einem WIFI-Netzwerk herzustellen, bis der BLE-Scan eingeschaltet ist. (Ich bin mir nicht sicher über Mobilfunknetze und mobiles Internet).
Dies geschah definitiv auf folgenden Geräten:

  • Nexus 7
  • Motorola Moto G.

Das BLE-Scannen mit aktiviertem WIFI schien jedoch ziemlich stabil zu sein:

  • Samsung S4
  • HTC One

Meine Problemumgehung

Ich scanne BLE für einen kurzen Zeitraum von 3-4 Sekunden und schalte dann den Scan für 3-4 Sekunden aus . Dann wieder EIN.

  • Natürlich schalte ich den BLE-Scan immer aus, wenn ich eine Verbindung zu einem BLE-Gerät herstelle.
  • Wenn ich die Verbindung zu einem Gerät trenne, starte ich BLE neu (Adapter aus- und wieder einschalten), um den Stapel zurückzusetzen, bevor ich erneut mit dem Scan beginne.
  • Ich habe auch BLE zurückgesetzt, wenn ich es erkenne servicesoder characteristicsfehlschlage.
  • Wenn ich Werbedaten von einem Gerät erhalte, mit dem die App eine Verbindung herstellen soll (sagen wir 500 Mal, ohne eine Verbindung herstellen zu können - das sind etwa 5-10 Sekunden Werbung), setze ich BLE erneut zurück.
benka
quelle
Sie sagten, ich starte BLE neu, nachdem ein Gerät getrennt wurde. Angenommen, der Benutzer hat die Datei über eine Bluetooth-Verbindung übertragen. Dann wird die Bluetooth-Übertragung jederzeit fehlschlagen.
Rahul Rastogi
1
Was meinst du mit "Adapter aus- und wieder einschalten"?
Marian Paździoch
Ich bin damit einverstanden, dass Wifi und Bluetooth zusammen die App-Leistung in Moto G
Nigilan
@ MarianPaździoch, mit "Adapter aus- und wieder einschalten" @ benka bedeutet BluetoothAdapter
Anup
9

Stellen Sie sicher, dass Ihr Nexus mit dem Gerät gekoppelt ist. Ich kann nicht überprüfen, ob die Kommunikation ordnungsgemäß funktioniert oder nicht, aber Sie können ohne Neustart mehrmals eine Verbindung herstellen. Es scheint, dass die erste Verbindung kein Pairing erfordert, aber alle nachfolgenden Versuche tun dies.

Ich werde diese Antwort in ein paar Tagen aktualisieren, wenn ich die Serviceerkennung teste und Lese- und Schreibanforderungen ohne Neustart erhalte.

BEARBEITEN: Es stellte sich heraus, dass ich eine Entwicklungs-Firmware-Version (unseren Sensor) getestet habe, die Probleme verursachte, wenn sie nicht gekoppelt wurde. Unser neuester Firmware-Build für die Produktion funktioniert einwandfrei für die 2540er und 2541er.

BEARBEITEN: Ich habe festgestellt, dass auf dem Nexus 7 2013 die Verbindungen stabiler sind, wenn WLAN ausgeschaltet ist. Ich würde gerne wissen, ob dies jemand anderem hilft.

EDIT: Ich habe es anscheinend mit Pairing rückwärts gehabt. Alles funktioniert gut, wenn nicht gepaart. Nach dem Pairing treten genau die gleichen Symptome wie beim OP auf. Es ist nur noch nicht bekannt, ob dies mit unserer Firmware oder der Android BLE API zusammenhängt. Seien Sie vorsichtig, wenn Sie dies testen, da Sie nach dem Pairing aufgrund eines in 3b dieses Beitrags erläuterten Fehlers möglicherweise nicht mehr das Pairing durchführen können .

Mikt25
quelle
Ich verbinde und verbinde mich ständig mit einem CC2541-Gerät, ohne dass eine manuelle Kopplung oder ein Neustart erforderlich ist.
dgel
Meiner Meinung nach ist keine Paarung erforderlich. Die offiziellen Dokumente kommentieren das Pairing auch nicht. Ich könnte auch eine Benachrichtigung zum Schreiben, Lesen und Ändern von Merkmalen ohne Kopplung durchführen. Allerdings nur für kurze Zeit. Jetzt ist es wieder wackelig ... Der SAMSUNG BLE SKD v2.0 erforderte ebenfalls kein Pairing und funktionierte recht gut.
OneWorld
3
Ich kann bestätigen, dass es nach dem Ausschalten von Wifi stabiler ist. Jeder sollte das versuchen.
OneWorld
1
Ob ein Pairing erforderlich ist oder nicht, hängt von der Geräteimplementierung ab. Für nrf8002-Geräte ist ein Pairing erforderlich, und die Samsung 2.0- und 1.2-APIs unterstützen dies. Es scheint, als ob der offizielle API-Support Probleme mit dem Pairing-Aspekt hat, da es nach dem Pairing eines ble-Geräts unmöglich ist, die Kopplung aufzuheben!
Chris Herbert
2
Ich habe ein Problem damit, dass ich mich nicht trennen kann. 1) Gehen Sie zu Ihrem BT-Menü, wählen Sie "Entkoppeln", entfernen Sie das ble-Gerät aus dem Bereich oder schalten Sie es aus, wählen Sie das ble-Gerät im bt-Menü aus, und es wird versucht, eine Verbindung herzustellen und einen Fehler zu verursachen. Setzen Sie dann Bluetooth zurück. Beim Zurücksetzen wird das Gerät nicht gepaart.
Chris Herbert
7

Bei einigen Modellen liegt ein Defekt vor: https://code.google.com/p/android/issues/detail?id=180440

Andererseits bestand in meinem Fall das Problem darin, dass meine Verbindung in der onDestroy-Methode nicht ordnungsgemäß geschlossen wurde. Nach dem korrekten Schließen besteht für mich kein Problem, unabhängig davon, ob das WLAN ein- oder ausgeschaltet ist.

btGatt.disconnect();
btGatt.close();
Krystian
quelle
Warum ist closenotwendig?
IgorGanapolsky
3
Das richtige Schließen ist der Schlüssel, wenn Sie Bluetooth mehrmals verbinden möchten. Nach meiner Erfahrung funktioniert es am besten, wenn Sie Ihre Ble-Verbindung in einem separaten UNBOUND-Dienst ausführen, damit Sie sie von Hand starten und stoppen können. Und dass Sie mConnectedGatt.disconnect () aufrufen; ble_device = null; in deinem inDestroy (). In meinem Fall funktioniert dieses Muster problemlos stabil.
MedTech
4

Ich hatte ein ähnliches Problem. Mein Fix war

if (Build.VERSION.SDK_INT >= 23) {
  mBluetoothGatt = device.connectGatt(this, false, mGattCallback, BluetoothDevice.TRANSPORT_LE);
} else {
  mBluetoothGatt = device.connectGatt(this, false, mGattCallback);
}

& Anruf nach dem Trennen schließen.

Sam Reyes
quelle