Jak podłączyć urządzenie z systemem Android do urządzenia iOS przez BLE (Bluetooth Low Energy)

82

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

edoardotognoni
źródło
2
Zgodnie z dokumentacją, Android OBSŁUGUJE działanie jako serwer (na przykład monitor pracy serca), chociaż wartości, które generuje, będą fałszywe. Z drugiej strony nie ma przykładów, dokumentacja mówi ci o zrobieniu złych rzeczy i nie ma sposobu na rozpoczęcie reklam (chociaż dokumentacja mówi, że możesz).
Brian Reinhold
Masz rację. Znalazłem już błąd w dokumentacji dotyczący BluetoothGattServer. Nie możesz mieć instancji GattServer z metodą getProfileProxy (jak mówi dokument), ale możesz z BluetoothManager.openGattServer (). Zostało to już zgłoszone Google jako problem. W każdym razie tak, Android może działać jako GattServer, ale nie może się reklamować. Jeśli jesteś zainteresowany, już przetestowałem i po połączeniu 2 urządzeń pilot widzi serwery Gatt wystawione z Androida. Sprawdź komentarze pierwszej odpowiedzi, aby zobaczyć mój raport dotyczący tego pytania.
edoardotognoni
Tak, ja też się na to natknąłem i dodałem swoje dwa centy do tego numeru. Teraz mam serwer termometru, który nie może reklamować, więc nie mogę go używać.
Brian Reinhold,
Otworzyłem wątek prawie identyczny z twoim: stackoverflow.com/questions/18410081/… Będę obserwował ten wątek pod kątem wszelkich znalezionych rozwiązań.
afrederick
Przeczytaj problem z Androidem, który zamieściłem w sekcji EDYTUJ pytania. To jasno wyjaśnia, dlaczego ten proces zawodzi. Uważamy, że to wina Androida. Głównie jest to wysyłanie niedozwolonych wiadomości przez ustalony kanał BLE. Myślę, że jedyne, co możemy zrobić, to poczekać na nową wersję Androida :(
edoardotognoni,

Odpowiedzi:

7

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:

  1. Strona peryferyjna: Zatrzymaj reklamowanie możliwości BR / EDR, dostosowując odpowiednie flagi ( link )
  2. Strona środkowa: Ustaw parametr transportu jawnie na TRANSPORT_LE, wywołując ukrytą wersję connectGatt () za pomocą refleksji

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 .

Dominik Gebhart
źródło
Dzięki, to dla mnie działa, zauważ, że w Androidzie M google dodało przeciążenie dla metody connectGatt, która pobiera zmienną transportową: connectGatt (Context context, boolean autoConnect, BluetoothGattCallback callback, int transport)
arbel03
1
Och, dzięki za tę wskazówkę, więc wreszcie ją udostępnili.
Dominik Gebhart,
2

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.

omikes
źródło
2

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.

p2pkit
źródło
1

Możesz teraz przejść TRANSPORT_LEprzez BluetoothDevice.connectGattAPI 23.

Zobacz odniesienia do dokumentacji Androida poniżej:

Kevin Crain
źródło
0

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.

Mustafa Demir
źródło