Существует несколько различий между «автоматическим подключением» и сканированием + «прямое подключение». В идеале «автоматическое подключение» - это то, что нам нужно, поскольку для установки соединения требуется только один рекламный пакет, а не два.
Параметры сканирования
Для автоматического подключения, прямого подключения и сканирования используется различное сканированиепараметры при прослушивании рекламы. Используемый вами режим и рекламный интервал сильно влияют на время установки соединения.
Автоматическое подключение использует окно 48 мс каждые 1280 мс во всех не древних версиях Android и используется всеми поставщиками. насколько мне известно. Это очень хорошо работает, когда рекламное устройство имеет короткий рекламный интервал, например 20 мс. Я полагаю, что ваш автомобиль может разорвать этот короткий рекламный интервал, когда автомобиль запускается, и, возможно, увеличить интервал, если какое-то время соединение не установлено. Если используется рекламный интервал 20 мс, соединение должно быть установлено в течение 1280 мс, поскольку по крайней мере один пакет должен быть перехвачен в течение 48 мс, когда на устройстве Android включена радиосвязь. Однако, если вы размещаете рекламу с интервалом в 1 секунду, для подключения может потребоваться очень много времени, так как объявление должно быть отправлено точно в этот интервал 48 мс, равный 1280 мс.
Directconnect использует окно примерно 30 мс каждые 60 мс для быстрой настройки соединения. Однако через 30 секунд прямое соединение прерывается и отправляет сообщение об ошибке в обратном вызове onConnectionStateChange
. Поэтому этот режим следует использовать только в графическом интерфейсе пользователя, когда пользователь нажимает кнопку «Подключиться», или после того, как какое-то сканирование выполнено, и вы хотите подключиться к устройству, найденному во время сканирования.
Обычная операция сканирования использует совершенно другое окно сканирования и интервалы сканирования. Исторически 1-секундное окно сканирования и 5-секундный интервал сканирования использовались для «низкого энергопотребления», а 5-секундное окно сканирования и 5-секундный интервал сканирования использовались для «малой задержки». В более поздних версиях Android это стало намного хуже, например, интервал сканирования 15 или 45 секунд, в то время как окно не увеличилось.
Работа с неожиданными остановками
Со временем фоновое сканирование на Android становится все более и более ограниченным, и вы должны быть осторожны с настройками сканирования, фильтрами сканирования, частотой и временем сканирования, чтобы убедиться, что устройство Android действительно сканирует ваши устройства BLE. К счастью, в Android 8 были добавлены новые API, использующие Pending Intents, чтобы система могла сканировать ваши устройства, даже если ваше приложение было убито системой для экономии памяти. Вы должны прочитать http://www.davidgyoungtech.com/2017/08/07/beacon-detection-with-android-8, который сравнивает кучу вариантов сканирования. Однако эта статья, похоже, не затрагивает тот случай, когда у вас есть служба Foreground (для которой требуется значок в панели уведомлений, указывающий пользователю, что ваше приложение работает), что значительно снижает все ограничения.
Никаких ограничений на «автоматическое подключение» не было добавлено, однако, в течение многих лет. Единственное «ограничение», о котором я знаю, это то, что в вашем приложении должна быть служба Foreground Service, чтобы приложение не было убито и, следовательно, потеряло ваши попытки подключения.
Stability
Конечно, в стеке Android Android есть куча ошибок, некоторые из которых были исправлены, а некоторые остались. Есть также предполагаемое поведение, которое приведет к нестабильности - например, когда Android останавливает сканирование, когда считает, что вы слишком много сканируете.
Независимо от того, какой метод вы используете, если вы хотите, чтобы соединения сохранялись после выключения пользователя ив Bluetooth (или в случае сбоя и перезапуска стека Bluetooth) необходимо иметь BroadcastReceiver, который прослушивает BluetoothAdapter.ACTION_STATE_CHANGED
, который перезапускает все ожидающие подключения / сканирования. Возможно, вы также захотите настроить BroadcastReceiver, который будет прослушивать при загрузке системы или обновлении вашего приложения, чтобы запускать ваше приложение в этих сценариях, чтобы вы могли запускать ожидающие соединения.
Может быть, это не так уж важно для вашего случая, но независимо от того, какой метод подключения вы используете, вы также должны знать, что у Android есть ограничения на максимальные подключения, объекты BlueoothGatt, ссылки L2CAP и другие вещи, которые могут привести к сбою связи внеожиданные пути. Иногда из-за ошибок в обратном вызове onConnectionStateChange
, а иногда и без обратных вызовов, что ограничение достигнуто.
Для "автоматического подключения" вам действительно нужно реализовать что-то вроде https://github.com/Polidea/RxAndroidBle/blob/7663a1ab96605dc26eba378a9e51747ad254b229/rxandroidble/src/main/java/com/polidea/rxandroidble2/internal/util/BleConnectionCompat.java, если вы знаете, что у вас работают устройстваAndroid 6 или ниже, из-за https://issuetracker.google.com/issues/36995652, который вызывает «прямое подключение» вместо «автоматическое подключение».
Для «автоматического подключения» я написал важный патч https://android.googlesource.com/platform/system/bt/+/8451ad010e26562d4a4c7d0d135c70c4325ee6b5 это было принято в Android 8.1, что ранее приводило к зависанию стека Bluetooth до его перезапуска, если устройство истекло, а затем перезапустило рекламу до истечения времени ожидания для устройства Android.
Когда ваш код выполняется на устройстве, недавно установленномдля поддержки передачи TRANSPORT_LE
в connectGatt
, используйте этот метод, так как в противном случае Android иногда пытается подключиться с помощью Bluetooth Classic.
Адреса устройств Bluetooth
Из-за ужасного недостатка дизайна, невозможно указать стеку Bluetooth подключиться по полному адресу (тип адреса random / public + address). Вы можете указать 48-битный адрес только тогда, когда хотите получить объект BluetoothDevice
(который вы затем используете для подключения). Копаясь в исходном коде стека Bluetooth для Android, везде возникает та же проблема, что устройство Bluetooth идентифицируется по 48-битному адресу вместо 49-битного. Их «быстрое решение» заключалось в добавлении свойства к информации об устройстве, которое указывает, имеет ли устройство открытый или случайный адрес. Этот бит не может быть установлен приложением, но устанавливается только во время сканирования. При соединении с connectGatt
и типом адреса неизвестно, он попытается установить, используя публичный тип адреса (несколько подверсий Android 7 сделали несколько глупых предположений о типе адреса в зависимости от некоторых бит в 48-битном адресе при использовании"автоматическое подключение"). Если ваши устройства BLE имеют статический случайный адрес, он не будет подключаться. Выполнив сканирование и обнаружив ваше устройство, оно сохранит адрес устройства и тип адреса в таблице в ОЗУ, поэтому, если вы позже подключитесь к нему с помощью connectGatt
, это будет успешным, поскольку теперь используется правильный тип адреса. Эта таблица очищается при перезапуске Bluetooth. Обратите внимание: если вы выполняете связывание, информация об устройстве записывается на диск, включая тип адреса, поэтому подключение к подключенным устройствам всегда должно работать, даже если Bluetooth перезапущен.
Сводка
Несмотря на всеПри описанных выше проблемах «автоматическое подключение», как правило, работает безупречно и очень стабильно, если вы следуете приведенным выше рекомендациям, что дает вам быстрое время установки соединения при условии, что ваше периферийное устройство имеет короткий рекламный интервал. В Android 8.1 и более поздних версиях большинство критических ошибок было исправлено.
Ваш второй выбор, вероятно, заключается в использовании параметра сканирования в ожидании, когда вы получаете сообщение от системы при обнаружении вашего устройства (даже если это можетзаймет некоторое время, прежде чем ваше устройство будет обнаружено). Конечно, вы можете использовать оба метода, чтобы быть в безопасности ...