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


82

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

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

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

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

Благодарю.

РЕДАКТИРОВАТЬ: после некоторого жесткого тестирования я поднял проблему на странице AOSP. Это можно проверить здесь


2
Согласно документации, Android ДЕЙСТВИТЕЛЬНО поддерживает работу в качестве сервера (например, монитора сердечного ритма), хотя генерируемые значения будут поддельными. С другой стороны, примеров нет, документация говорит вам делать неправильные вещи, и нет возможности запускать рекламу (хотя в документации сказано, что вы можете).
Брайан Рейнхольд

Вы правы. Я уже нашел ошибку в документации о BluetoothGattServer. У вас не может быть экземпляра GattServer с методом getProfileProxy (как говорится в документе), но вы можете использовать BluetoothManager.openGattServer (). Об этом уже сообщалось в Google как о проблеме. В любом случае, да, Android может действовать как GattServer, но не может рекламировать. Если вам может быть интересно, я уже тестировал, и после подключения двух устройств удаленный может видеть серверы Gatt, открытые с Android. Просмотрите комментарии к первому ответу, чтобы увидеть мой отчет о проблеме по этому вопросу.
edoardotognoni 08

Да, я тоже наткнулся на это и добавил свои два цента к этому вопросу. Теперь у меня есть сервер Thermometer, который не может рекламироваться, поэтому я не могу его использовать.
Брайан Рейнхольд

Я открыл тему, почти идентичную вашей: stackoverflow.com/questions/18410081/… Я буду следить за этой веткой, чтобы найти любые решения, которые вы найдете.
afrederick

Прочтите проблему Android, которую я опубликовал в разделе EDIT вопроса. Это ясно объясняет, почему этот процесс терпит неудачу. мы думаем, что это ошибка Android. В основном это отправка недопустимого сообщения по фиксированному каналу BLE. Я думаю, что единственное, что мы можем сделать, это дождаться нового релиза Android :(
edoardotognoni

Ответы:


7

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

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

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

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

  1. Периферийная сторона: прекратите рекламировать возможности BR / EDR, настроив соответствующие флаги ( ссылка )
  2. Центральная сторона: явно установите для параметра транспорта значение 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

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


Спасибо, это работает для меня, обратите внимание, что в android M Google добавил перегрузку для метода connectGatt, который принимает транспортную переменную: connectGatt (Контекст контекста, логическое autoConnect, обратный вызов BluetoothGattCallback, int transport)
arbel03

1
О, спасибо за подсказку, наконец-то они сделали ее доступной.
Доминик Гебхарт

2

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


2

Может, немного задержался, но, возможно, вашу боль можно будет немного облегчить;)

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

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

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

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



0

Устройства iOS всегда могут быть периферийными или центральными, но устройства Android не могут быть редко. В этом случае ваше устройство iOS должно быть периферийным, а Android должен быть центральным. Мы можем думать, что периферийное устройство - это сервер, а центральное - это клиент. Это просто.

Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.