Обнаружение подключения устройства BLE на Android

Я работаю над проектом по настройке маяков. Через определенное время после включения питания маяк становится неконфигурируемым, пока он не включится. Чтобы показать список настраиваемых маяков, я рассматриваю некоторые характеристики (имя устройства Bluetooth, определенные данные производителя в рекламном пакете). Мне также нужно знать, является ли он «подключаемым», т. Е. Если тип PDU в рекламном пакете BLE для устройства указывает, что он подключается. Я искал классы Android Bluetooth высокого и низкого уровня, как в Android 4.X, так и 5.X, и не смог найти ничего, что сообщит мне эту информацию.

Я понимаю, что одним из способов определения возможности подключения маяка является подключение к нему, например: device.connectGatt(...) . Тем не менее, я видел, что это занимает более двух минут, прежде чем обратный вызов onConnectionStateChange возвращается с STATE_DISCONNECTED . Кроме того, в среде могут быть многие из этих маяков, и соединение с каждым, которое может быть настроено, будет неэффективным.

Эквивалент iOS этого атрибута может быть найден в словаре advertisementData в ключе под CBAdvertisementDataIsConnectable в CBCentralManagerDelegate обратного вызова centralManager:didDiscoverPeripheral:advertisementData:RSSI .

Итак, возникает вопрос: существует ли способ на Android определить, является ли устройство BLE «подключаемым» к рекламным данным или результатам сканирования или …?

UPDATE: AS завершенных API-интерфейсов в SDK Android O, класс ScanResult (сам добавленный с Android 5.0) теперь имеет метод isConnectable() . Обнаружение подключаемых рекламных объявлений возможно только на Android 8.0+. См. Здесь для получения дополнительной информации: https://developer.android.com/reference/android/bluetooth/le/ScanResult.html#isConnectable ()

До Android 8.0, к сожалению, это невозможно.

Подключаемая реклама определяется байт заголовка PDU 0. Вы можете увидеть это в приведенной ниже структуре примера:

 d6 be 89 8e # Access address for advertising data (this is always the same fixed value) 40 # Advertising Channel PDU Header byte 0. Contains: (type = 0), (tx add = 1), (rx add = 0) 24 # Advertising Channel PDU Header byte 1. Contains: (length = total bytes of the advertising payload + 6 bytes for the BLE mac address.) 05 a2 17 6e 3d 71 # Bluetooth Mac 

Проблема заключается в устройствах до Anroid 8.0, API сканирования Android не дает вам доступа к этим заголовкам. Вы получаете ровно три поля в обратном вызове от Android 4.x:

 onLeScan(BluetoothDevice device, rssi, byte[] scan data) 

Массив байтов данных сканирования начинается после упомянутых выше байтов заголовка. И из того, что я вижу в определении BluetoothDevice , ни одно из полей или методов не говорит вам, является ли это подключаемой рекламой – класс является просто контейнером для mac-адреса bluetooth с методами осуществления функций в стеке bluetooth. И нет никаких методов в IBluetooth.aidl который является частным интерфейсом к IBluetooth.aidl bluetooth (и то, что BluetoothDevice вызывает для получения информации), которое может получить этот флаг.

Похоже, что эта информация не передается до уровня Java из пакета BlueDroid до Android 8.0.

Это должно быть возможно, так как это делает мастер-панель Nordic's nRF.

После некоторого рытья я думаю, что знаю, как это делается. Я не уверен, что это правильный способ сделать это.

Я попытался использовать рекламодателя LE и установить устройство как подключаемое. В приложении Nordic устройство устанавливается как подключаемое в зависимости от байтов, найденных в scanResult.getFlags ().

Я обнаружил, что этот код работает для моих устройств:

 int flags = scanResult.getScanRecord().getAdvertiseFlags(); if ((flags & 2) == 2) { //connectable } 
Intereting Posts