Как подключить устройство Android к устройству iOS через BLE (Bluetooth Low Energy)

Я пытаюсь создать приложение, использующее новый Bluetooth Low Energy API для Android. Для этого я начал с образца BLE, приходящего с уровнем API уровня 18.

Поскольку я читал, что Android не может выступать в качестве периферии, я помещаю телефон Android в центральный режим, просматривая устройства BLE вокруг него. Для этой цели я провел несколько испытаний с помощью Nordic Platform, имитирующей датчик сердца. Все работает идеально!

После этого я пытаюсь выбрать iPhone (iOS 7 beta 4) и поместить его в Peripheral way и имитировать датчик сердечного ритма как предыдущее тестирование. Приложение Android может видеть устройство и подключаться к нему. Но после того, как соединение активировано, два устройства отключаются друг от друга через 3-4 секунды. В дополнение к этому, когда я вызываю DiscoverServices() на стороне Android, никакой обратный вызов не срабатывает! В некоторых случаях устройство Android получает событие "Подключено", даже если чип IOS Bluetooth выключен. Это очень странно. Чтобы доказать это, я поместил Nordic Board в центральном режиме, и я правильно смог подключиться к устройству iOS без проблем.

Что это может быть? Есть некоторые ограничения на Android или iOS, которые не позволяют подключаться с Android до iOS или наоборот?

Спасибо.

EDIT: после некоторого жесткого тестирования я поднял вопрос на странице AOSP. Это можно проверить здесь

Ответ 1

Добавление сводки для справки:

Что это может быть? Есть некоторые ограничения на Android или iOS, которые не позволяют подключаться с Android до iOS или наоборот?

При подключении к серверу GATT, который рекламируется как устройство с двойной связью (BLE и BR/EDR), вызывая connectGatt (...), флаг TRANSPORT_AUTO, который добавляется внутри страны, делает Android по умолчанию режимом BR/EDR (ссылка).

Возможны следующие обходные пути:

  • Периферийная сторона: прекратите рекламировать возможности BR/EDR, настроив соответствующие флаги (ссылка)
  • Центральная сторона: задайте параметр транспорта для TRANSPORT_LE, вызвав скрытую версию connectGatt(), используя отражение

Пример:

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);    
   ... 
}

Редактировать 4/2016

Как отметил Arbel Israel, Google представил перегруженную версию connectGatt (...), который позволяет указать транспорт в Android M.

Ответ 2

Я написал простой рабочий пример, довольно простой и включил его в open source на Github: https://github.com/GitGarage. Пока он протестирован только с Android Nexus 9 и iPhone 5, но я полагаю, что он также будет работать с Nexus 6 и различными типами iPhone. Пока что он настроен явно для связи между одним Android и одним iPhone, но я полагаю, что он способен делать гораздо больше.

Ответ 3

Возможно, немного задержка, но, возможно, ваша боль может быть немного облегчена;)

Мы много экспериментировали с кросс-платформенными соединениями BLE (iOS ↔ Android) и узнали, что по-прежнему существует много несовместимостей и проблем с подключением. Помимо нестабильности Android, вы также должны учитывать, что на сегодняшний день не так много Android-устройств фактически поддерживают режим периферийных устройств BLE.

Поэтому, если ваш прецедент связан с функцией, и вам нужен только базовый обмен данными, я бы предложил посмотреть на Frameworks и библиотеки, которые могут обеспечить взаимодействие между платформами для вас, без необходимости создавать его с нуля.

Например: http://p2pkit.io или google рядом

Отказ от ответственности: я работаю на Uepaa, разрабатывая p2pkit.io для Android и iOS.