Próbuję stworzyć aplikację korzystającą z nowego interfejsu API Bluetooth Low Energy w systemie Android. W tym celu zacząłem od przykładu BLE pochodzącego z poziomu API 18 .
Kiedy przeczytałem, że Android nie może działać jako urządzenie peryferyjne, ustawiam telefon z Androidem w trybie centralnym, skanując w poszukiwaniu urządzeń BLE wokół niego. W tym celu przeprowadziłem testy na platformie Nordic symulującej czujnik serca. Wszystko działa perfekcyjnie!
Następnie próbuję wybrać iPhone'a (iOS 7 beta 4) i ustawić go w sposób peryferyjny i symulować czujnik tętna, tak jak w poprzednim teście. Aplikacja na Androida może zobaczyć urządzenie i połączyć się z nim. Ale po aktywowaniu połączenia 2 urządzenia rozłączają się od siebie w ciągu 3-4 sekund. Oprócz tego, kiedy wywołuję DiscoverServices () po stronie Androida, żadne wywołanie zwrotne nie jest wyzwalane! W niektórych przypadkach urządzenie z systemem Android odbiera zdarzenie „Połączono”, nawet jeśli układ Bluetooth iOS jest wyłączony. To jest bardzo dziwne. Aby to udowodnić, przestawiłem Nordic Board w tryb centralny i udało mi się bez problemu połączyć się z urządzeniem iOS.
Co to mogło być? Istnieją pewne ograniczenia w systemie Android lub iOS, które nie pozwalają na połączenie z Androida na iOS lub odwrotnie?
Dzięki.
EDYCJA: Po kilku trudnych testach zgłosiłem problem na stronie AOSP. Można to sprawdzić tutaj
źródło
Odpowiedzi:
Dodanie podsumowania w celach informacyjnych:
Co to mogło być? Istnieją pewne ograniczenia w systemie Android lub iOS, które nie pozwalają na połączenie z Androida na iOS lub odwrotnie?
Podczas łączenia się z serwerem GATT, który jest ogłaszany jako urządzenie dualmode (BLE i BR / EDR) przez wywołanie connectGatt (...), flaga TRANSPORT_AUTO, która jest dodawana wewnętrznie, powoduje, że Android domyślnie przechodzi w tryb BR / EDR ( link ).
Możliwe są następujące obejścia:
Przykład:
public void connectToGatt(BluetoothDevice device) { ... Method m = device.getClass().getDeclaredMethod("connectGatt", Context.class, boolean.class, BluetoothGattCallback.class, int.class); int transport = device.getClass().getDeclaredField("TRANSPORT_LE").getInt(null); // LE = 2, BREDR = 1, AUTO = 0 BluetoothGatt mGatt = (BluetoothGatt) m.invoke(device, this, false, gattCallback, transport); ... }
Edycja 4/2016
Jak Arbel izraelski zwrócił uwagę w komentarzu, Google wprowadził przeciążony wersję connectGatt (...) , która pozwala określić transportu w Android M .
źródło
Napisałem prosty, działający przykład, stosunkowo prosty, i umieściłem go na Github jako open source: https://github.com/GitGarage . Do tej pory był testowany tylko z Androidem Nexus 9 i iPhone'em 5s, ale przypuszczam, że działałby również z Nexusem 6 i różnymi typami iPhone'a. Jak dotąd jest skonfigurowany do komunikacji między jednym Androidem a jednym iPhonem, ale zakładam, że można go dostosować, aby zrobić znacznie więcej.
źródło
Może trochę z opóźnieniem, ale być może twój ból będzie trochę złagodzony;)
Dużo eksperymentowaliśmy z wieloplatformowymi połączeniami BLE (iOS <-> Android) i dowiedzieliśmy się, że nadal istnieje wiele niezgodności i problemów z połączeniem. Pomijając niestabilność Androida, należy również wziąć pod uwagę, że na dzień dzisiejszy niewiele urządzeń z Androidem obsługuje tryb BLE Peripheral.
Dlatego, jeśli Twój przypadek użycia jest oparty na funkcjach i potrzebujesz tylko podstawowej wymiany danych, sugerowałbym przyjrzenie się ramom i bibliotekom, które mogą osiągnąć komunikację między platformami, bez konieczności tworzenia jej od podstaw.
Na przykład: http://p2pkit.io lub google w pobliżu
Zastrzeżenie: Pracuję dla Uepaa, rozwijam p2pkit.io na Androida i iOS.
źródło
Możesz teraz przejść
TRANSPORT_LE
przezBluetoothDevice.connectGatt
API 23.Zobacz odniesienia do dokumentacji Androida poniżej:
źródło
Urządzenia z systemem iOS zawsze są urządzeniami peryferyjnymi lub centralnymi, ale urządzenia z Androidem rzadko się zdarzają. w tym przypadku urządzenie z systemem iOS musi być urządzeniem peryferyjnym, a android musi być centralnym. możemy pomyśleć, że urządzenie peryferyjne to serwer, a centrala to klient. to proste.
źródło