BLE: получение BluetoothDevice через BluetoothAdapter#getRemoteDevice() против сканирования

Сценарий:

Учитывая, устройство, которое всегда включено, и делает рекламу Bluetooth Low Energy каждую секунду.
Мне нужно реализовать приложение для планшетов Android, которое подключается к этому устройству через Bluetooth Low Energy, отправляет некоторые команды и затем отключается от него.
Минимальная версия Android: та, которая работает лучше всего, я волен решать. Я начал с API 21 (Android 5.0, Lollipop)

Выпуск:

Проблемы, возникающие в стеке BLE, также вызывали у меня проблемы: я хотел бы создать успешное прямое соединение с использованием объекта, полученного с помощью метода BluetoothAdapter#getRemoteDevice(MACAddress: String), и оно всегда терпит неудачу.

Результаты моего исследования:

Ниже приведены вопросы / ответы / сообщения, которые я нашел и которые кажутся полезными (может быть, они кому-нибудь помогут):

Вопросы:

Помимо этого, я изучил исходный код BluetoothDevice и обнаружил, что параметр Context метода connectGatt() вообще не используется:
https://android.googlesource.com/platform/frameworks/base/+/master/core/java/android/bluetooth/BluetoothDevice.java#1899
Хотите знать, может ли это быть одной из причин недостатков стека BLE?

Кроме того, я не понимаю, в чем разница между объектом BluetoothDevice, полученным сканером, и объектом, полученным BluetoothAdapter#getRemoteDevice(MACAddress: String).
Если я запускаю прямое соединение (параметр autoconnect установлен на false при вызове connectGatt()) на устройстве, полученном при сканировании, соединение обычно происходит успешно. Но прямое соединение всегда терпит неудачу (status = 133, timeout), когда используется объект, полученный getRemoteDevice ().

Поскольку устройство, к которому я хочу подключиться, объявляет себя каждую секунду, я ожидаю, что прямое подключение будет работать всегда / большую часть времени, как в случае сканирования.
Поскольку фоновое соединение (для параметра autoconnect установлено значение true) очень медленное, я не могу на это полагаться.
Кроме того, поскольку сканирование ненадежное и медленное, я не могу заставить пользователя ждать каждый раз, когда приложение запускается.

Подводя итог моим вопросам:

  • Параметр Context метода connectGatt() вообще не используется - может ли это быть одной из причин недостатков стека BLE? Я полагаю, кто-то положил это по уважительной причине.
  • В чем разница между объектом BluetoothDevice, полученным сканером, и объектом, полученным методом BluetoothAdapter#getRemoteDevice(MACAddress: String)?

1 ответ

Решение
  1. Параметр context использовался в более ранних версиях Android, но, видимо, больше не был нужен. Вы все равно должны передать действительный контекст, чтобы быть совместимым с более ранними версиями или более новыми, если они решат использовать его снова.

  2. Там не должно быть никакой разницы. Но если вы просто подключитесь по адресу устройства Bluetooth, вы заметите недостаток API в том, что вы не можете передать тип адреса (публичный или случайный). Так что, если вы попытаетесь подключиться к статическому случайному адресу, это может произойти сбой, если вы сначала не отсканировали устройство. Это связано с тем, что Android хранит кеш адресов и тип адреса, который был в последней рекламе. Поэтому попробуйте сначала отсканировать и убедитесь, что вы видите устройство, к которому хотите подключиться. Затем попробуйте подключиться с помощью BluetoothAdapter#getRemoteDevice(MACAddress: String).

Другие вопросы по тегам