Android 4.3 Bluetooth Low Energy niestabilny

189

Obecnie opracowuję aplikację, która będzie korzystać z Bluetooth Low Energy (testowanie na Nexusie 4). Po rozpoczęciu pracy z oficjalnymi interfejsami API BLE w Androidzie 4.3 zauważyłem, że po pierwszym podłączeniu urządzenia rzadko jestem w stanie pomyślnie połączyć się z tym urządzeniem lub innym urządzeniem.

Zgodnie z instrukcjami tutaj , mogę z powodzeniem podłączyć do urządzenia, usługi skanowania i charakterystyki i odczytu / zapisu / odbierać powiadomienia, bez żadnych problemów. Jednak po rozłączeniu i ponownym połączeniu często nie mogę skanować usług / cech lub nie mogę zakończyć odczytu / zapisu. Nie mogę znaleźć w dziennikach niczego, co wskazywałoby, dlaczego tak się dzieje.

Gdy to się stanie, muszę odinstalować aplikację, wyłączyć Bluetooth i ponownie uruchomić telefon, zanim zacznie ponownie działać.

Za każdym razem, gdy urządzenie zostanie odłączone, wywołuję funkcję close () na obiekcie BluetoothGatt i ustawiam na zero. Jakieś spostrzeżenia?


EDYCJA:
Zrzuty dziennika: dla tych dzienników zrootowałem swój telefon i podniosłem poziomy śledzenia powiązanych elementów w /etc/bluetooth/bt_stack.conf

Udane połączenie - pierwsza próba po ponownym uruchomieniu telefonu i zainstalowaniu aplikacji. Jestem w stanie połączyć się, odkryć wszystkie usługi / cechy oraz czytać / pisać.

Nieudana próba 1 - to kolejna próba po rozłączeniu się z udanym połączeniem powyżej. Wygląda na to, że byłem w stanie odkryć cechy, ale pierwsza próba odczytu zwróciła wartość zerową i wkrótce potem się rozłączyła.

Nieudana próba 2 - przykład, w którym nie jestem nawet w stanie odkryć usług / cech.


EDYCJA 2:
Urządzenie, z którym próbuję się połączyć, oparte jest na układzie scalonym CC2541 TI. Otrzymałem TI SensorTag (również oparty na CC2541) do zabawy i odkryłem, że TI wydało wczoraj aplikację na Androida dla SensorTag. Jednak ta aplikacja ma ten sam problem. Przetestowałem to na dwóch innych Nexusach 4 z tym samym rezultatem: połączenie z SensorTag jest udane za pierwszym lub drugim razem, ale (zgodnie z logami) później nie wykrywa usług, powodując różnego rodzaju awarie. Zaczynam się zastanawiać, czy to problem z tym konkretnym układem?

sa.shadow
źródło
Prześlij pełne dzienniki telefonu od rozruchu aż do rozwiązania problemu.
AAnkit
3
Używam Samsunga Galaxy S4 z zainstalowanym wyciekającym systemem Android w wersji 4.3; po wielu połączeniach / rozłączeniach, kiedy odkryję usługi, losowo otrzymam 129 (GATT_INTERNAL_ERROR) i otrzymam onConnectionStateChange o statusie 133 (GATT_ERROR), stan = BluetoothProfile.DEVICE_DISCONNECTED.
reTs,
1
Raz lub dwa razy otrzymałem wiele oddzwonień o statusie 129 i 133 w krótkim czasie i nigdy nie mogłem otrzymać żadnego oddzwaniania w BluetoothGattCallback, dopóki nie uruchomię ponownie urządzenia (ale skanowanie jest w porządku).
reTs
1
Zapomnij powiedzieć, że testuję z około dziesięcioma urządzeniami wykorzystującymi układy TI (przepraszam, nie znam ich modeli) i jednym urządzeniem z układami skandynawskimi. Urządzenie z chipami nordyckimi nigdy nie zgłasza błędu (jednak nie wystarczy, aby udowodnić, że problem jest związany z TI)
reTs
1
Mogę potwierdzić, że ten problem nadal występuje na Samsungu Galaxy S5 (zarówno wersja kompilacji G900VVRU2BOG5, jak i G900VVRU2BOA8 ). Jeśli wyczyszczę dane z Ustawienia> Menedżer aplikacji >> Wszystko >> Bluetooth , to działa na chwilę.
IronBlossom

Odpowiedzi:

184

Ważne wskazówki dotyczące wdrażania

(Być może niektóre z tych wskazówek nie są już konieczne z powodu aktualizacji systemu operacyjnego Android).

  1. Niektóre urządzenia, takie jak Nexus 4 z Androidem 4.3, wymagają połączenia trwającego ponad 45 sekund przy użyciu istniejącej instancji gatt . Obejście: Zawsze zamykaj wystąpienia gatt przy rozłączaniu i twórz nowe wystąpienie gatt przy każdym połączeniu.
  2. Nie zapomnij zadzwonić android.bluetooth.BluetoothGatt#close()
  3. Rozpocznij nowy wątek w środku, onLeScan(..) a następnie połącz. Powód: BluetoothDevice#connectGatt(Context context, boolean autoConnect, BluetoothGattCallback callback)zawsze zawodzi, jeśli zostanie wywołany LeScanCallback() {...}.onLeScan(BluetoothDevice device, int rssi, byte[] scanRecord)w tym samym wątku na Samsung Galaxy S3 z Androidem 4.3 (przynajmniej dla kompilacji JSS15J.I9300XXUGMK6)
  4. Większość urządzeń filtruje reklamy
  5. Lepiej nie używaj android.bluetooth.BluetoothAdapter#startLeScan(UUID[] serviceUuids, LeScanCallback callback) tego parametru do filtrowania niektórych UUID usług, ponieważ jest on całkowicie uszkodzony w Samsung Galaxy S3 z Androidem 4.3 i ogólnie nie działa na 128-bitowych UUID .
  6. Gatt zawsze może przetwarzać jedno polecenie na raz . Jeśli kilka poleceń zostanie wywołanych krótko po drugim, pierwsze zostanie anulowane z powodu synchronicznej natury implementacji gatt.
  7. Często widzę nawet na nowoczesnych urządzeniach z Androidem 5, że Wi-Fi przeszkadza w bluetooth i odwrotnie. W ostateczności wyłącz Wi-Fi, aby ustabilizować Bluetooth.

Samouczek dla początkujących

Całkiem OK dla początkujących może być ten samouczek wideo: Tworzenie inteligentnych aplikacji Bluetooth na Androida http://youtu.be/x1y4tEHDwk0

Problem i obejście opisane poniżej zostały prawdopodobnie naprawione teraz przez aktualizacje systemu operacyjnego

Obejście: Mógłbym „ustabilizować” moją aplikację, robiąc to ...

  1. Zapewniam użytkownikowi ustawienie „Uruchom ponownie Bluetooth”. Jeśli to ustawienie jest włączone, ponownie uruchamiam Bluetooth w niektórych punktach, które wskazują, że początek stosu BLE staje się niestabilny. Np. Jeśli startScan zwraca false. Dobrym punktem może być również niepowodzenie usługi serviceDiscovery. Po prostu wyłączam i włączam Bluetooth.
  2. Podaję inne ustawienie „Wyłącz WiFi”. Jeśli to ustawienie jest włączone, moja aplikacja wyłącza Wi-Fi, gdy aplikacja jest uruchomiona (i włącza ją później)

To obejście oparte jest na doświadczeniach obserwacyjnych ...

  • Ponowne uruchomienie Bluetooth pomaga rozwiązać problemy z BLE w większości przypadków
  • Jeśli wyłączysz Wi-Fi, stos BLE stanie się znacznie bardziej stabilny. Działa to również dobrze na większości urządzeń z włączonym Wi-Fi.
  • Jeśli wyłączysz Wi-Fi, ponowne uruchomienie Bluetooth w pełni odzyskuje stos BLE bez potrzeby ponownego uruchamiania urządzenia w większości przypadków.
Jeden Świat
źródło
33
Google, musisz to teraz naprawić. To obejście (zrobiłem to plus, ponieważ działa) jest śmieszne.
Chris Herbert
4
Czasami odnajdowanie usługi zakończy się sukcesem ze statusem 0 (zakładając, że nie ma problemów), ale charakterystyczne odczyty przyniosą wartości NULL, ponieważ zasadniczo nie są tak naprawdę połączone lub właściwości nie zostały odkryte (widzę to w dzienniku: 11-01 18:37: 32.131: WARN / BluetoothGatt (20119): Nieobsługiwany wyjątek: java.lang.NullPointerException)
Lo-Tan,
2
@ Lo-Tan Zawsze po wykryciu usługi sprawdzam, czy moja oczekiwana usługa jest uwzględniona. Nigdy nie możesz być pewien, czy wykrycie usługi przyniesie jakikolwiek skutek. Czasami nie otrzymuję oddzwonienia. Zastosowałem więc limit czasu na wykrycie usługi.
OneWorld,
2
Moje doświadczenie to: Samsung S3 (4.3) ponownie nawiązał połączenie po zamknięciu klienta Gatt, jak opisano w paragrafie 2 powyżej; za pomocą Nexusa 4 i 7 (4.4.2) Nie mogłem się połączyć ponownie po zerwaniu połączenia, nawet po ponownym uruchomieniu adaptera BL, ale można go ponownie podłączyć automatycznie po 2 minutach
Konstantin Konopko
1
Czy każdy może potwierdzić, czy android.bluetooth.BluetoothGatt może obsłużyć tylko jedną oczekującą operację GATT NA URZĄDZENIE , NA PROCES lub OKRES (tj. We wszystkich procesach). Przypuszczam, że jest to DO URZĄDZENIA, ale ten problem jest tak zepsuty, że nie zaskoczyłoby mnie, gdyby było inaczej. Jeśli ograniczenie dotyczy tylko URZĄDZENIA, wówczas system operacyjny / urządzenie, które jest w stanie obsłużyć wiele jednoczesnych operacji, jest dowodem na to, że problem ten jest spowodowany jedynie słabą naiwną implementacją w instancji BluetoothAdapter, że system operacyjny przekazuje każdy proces (który, jak zakładałem, był singleton we wszystkich procesach).
swooby
18

Wyłączanie WIFI:

Mogę również potwierdzić, że wyłączenie WIFI sprawia, że ​​Bluetooth 4.0 jest bardziej stabilny, szczególnie w Google Nexus (mam Nexusa 7).

Problem

jest to, że tworzona przeze mnie aplikacja potrzebuje zarówno WIFI, jak i ciągłego skanowania LE Bluetooth . Wyłączenie WIFI nie było dla mnie opcją.

Ponadto zdałem sobie sprawę, że to ciągłe skanowanie LE Bluetooth może faktycznie zabić połączenie WIFI i sprawić, że adapter WIFI nie będzie mógł ponownie połączyć się z żadną siecią WIFI, dopóki skanowanie BLE nie zostanie WŁĄCZONE. (Nie jestem pewien sieci komórkowych i mobilnego internetu).
Zdecydowanie stało się to na następujących urządzeniach:

  • Nexus 7
  • Motorola Moto G

Jednak skanowanie BLE z włączoną siecią WIFI wydawało się dość stabilne na:

  • Samsung s4
  • HTC One

Moje obejście

I skanować ble na krótki okres czasu 3-4 sekundy potem wyłączyć skanowanie przez 3-4 sekund . Następnie włącz ponownie.

  • Oczywiście zawsze wyłączam skanowanie BLE, kiedy podłączam się do urządzenia BLE.
  • Po odłączeniu od urządzenia ponownie uruchamiam BLE (wyłączam i włączam adapter), aby zresetować stos przed ponownym uruchomieniem skanowania.
  • Zresetowałem również BLE podczas wykrycia serviceslub characteristicsniepowodzenia.
  • Kiedy otrzymuję dane reklamowe z urządzenia, z którym aplikacja powinna się połączyć (powiedzmy 500 razy bez możliwości połączenia - to około 5-10 sekund reklamy) resetuję BLE ponownie.
benka
źródło
Powiedziałeś, że ponownie uruchamiam BLE po odłączeniu urządzenia. Załóżmy, że użytkownik przesyłał plik przez połączenie Bluetooth. Następnie spowoduje to niepowodzenie transferu Bluetooth w dowolnym momencie.
Rahul Rastogi
1
co rozumiesz przez „wyłącz adapter, a następnie włącz”?
Marian Paździoch
Zgadzam się, że Wi-Fi i Bluetooth razem zabijają działanie aplikacji w Moto G.
Nigilan
@ MarianPaździoch, przez „wyłączenie adaptera, a następnie WŁĄCZENIE” @ benka oznacza BluetoothAdapter
Anup
9

Upewnij się, że Twój Nexus jest sparowany z urządzeniem. Nie mogę zweryfikować, czy komunikacja działa poprawnie, ale będziesz mógł połączyć się więcej niż jeden raz bez ponownego uruchamiania. Wydaje się, że pierwsze połączenie nie wymaga parowania, ale wszystkie kolejne próby wymagają.

Zaktualizuję tę odpowiedź za kilka dni, gdy przetestuję wykrywanie usługi i odczyta żądania odczytu i zapisu bez ponownego uruchamiania.

EDYCJA: Okazuje się, że testowałem wersję oprogramowania układowego (naszego czujnika), która powodowała problemy, jeśli nie została sparowana. Nasze najnowsze produkcyjne oprogramowanie układowe działa dobrze na modelach 2540 i 2541.

EDYCJA: Zauważyłem, że na Nexusie 7 2013 połączenia są bardziej stabilne, gdy Wi-Fi jest wyłączone. Chciałbym wiedzieć, czy to pomaga komukolwiek innemu.

EDYCJA: Wydaje mi się, że miałem parowanie wstecz. Wszystko działa dobrze, gdy nie jest sparowane. Po sparowaniu doświadczam dokładnie tych samych objawów, co OP. Po prostu nie wiadomo jeszcze, czy jest to związane z naszym oprogramowaniem układowym lub interfejsem API Android BLE. Zachowaj ostrożność podczas testowania, ponieważ po sparowaniu możesz nie być w stanie usunąć parowania z powodu błędu wyjaśnionego w 3b tego postu .

Mikt25
źródło
Konsekwentnie łączę się i ponownie podłączam do urządzenia CC2541 bez żadnego ręcznego parowania lub ponownego uruchamiania.
dgel
Moim zdaniem nie ma potrzeby parowania. Oficjalne dokumenty również nie komentują parowania. Mogłem również wykonywać zapisywanie, czytanie, charakterystyczne powiadomienia o zmianie bez żadnego parowania. Jednak tylko przez krótki czas. Teraz znów się trzęsie ... SAMSUNG BLE SKD v2.0 również nie wymagał parowania i działał całkiem dobrze.
OneWorld,
3
Mogę potwierdzić, że jest bardziej stabilny po wyłączeniu Wi-Fi. Każdy powinien tego spróbować.
OneWorld,
1
To, czy parowanie jest wymagane, czy nie, zależy od implementacji urządzenia. Urządzenia nrf8002 wymagają parowania, a oba interfejsy API Samsunga 2.0 i 1.2 obsługują to. Wygląda na to, że oficjalna obsługa interfejsu API ma problemy z aspektem parowania, ponieważ po sparowaniu pustego urządzenia nie można usunąć parowania!
Chris Herbert
2
Mam problem z niezdolnością do sparowania. 1) przejdź do menu bt, wybierz sparuj, usuń urządzenie ble z obszaru lub depoweruj go, wybierz urządzenie ble w menu bt, a ono spróbuje sparować się i zawieść, a następnie zresetować bluetooth. Po zresetowaniu urządzenie zostanie sparowane.
Chris Herbert
7

W niektórych modelach występuje wada: https://code.google.com/p/android/issues/detail?id=180440

Z drugiej strony w moim przypadku problemem było to, że moje połączenie nie zostało poprawnie zamknięte w metodzie onDestroy. Po prawidłowym zamknięciu problem dla mnie nie istnieje, bez względu na to, czy Wi-Fi jest włączone lub wyłączone.

btGatt.disconnect();
btGatt.close();
Krystian
źródło
Dlaczego jest to closekonieczne?
IgorGanapolsky
3
Prawidłowa procedura zamykania jest kluczowa, gdy chcesz połączyć Bluetooth wiele razy. Z mojego doświadczenia wynika, że ​​działa najlepiej, jeśli uruchamiasz połączenie Ble w oddzielnej usłudze UNBOUND, dzięki czemu możesz ręcznie uruchomić i zatrzymać. I że wywołujesz mConnectedGatt.disconnect (); ble_device = null; w twojej inDestroy (). W moim przypadku ten wzór działa stabilnie bez problemu.
medTech
4

Miałem podobny problem. Moja poprawka była

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

i dzwonienie blisko po rozłączeniu.

Sam Reyes
źródło