Android 4.3 Bluetooth энергосберегающий нестабильный


189

В настоящее время я занимаюсь разработкой приложения, которое будет использовать Bluetooth Low Energy (тестирование на Nexus 4). После начала работы с официальными API BLE в Android 4.3 я заметил, что после первого подключения устройства я редко могу успешно подключиться к этому устройству или любому другому устройству или связаться с ним.

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

Как только это произойдет, я должен удалить приложение, отключить Bluetooth и перезагрузить телефон, прежде чем он снова начнет работать.

Всякий раз, когда устройство отключается, я вызываю функцию close () для объекта BluetoothGatt и устанавливаю для него значение null. Есть идеи?


РЕДАКТИРОВАТЬ:
Лог дампов: для этих журналов я рутировал свой телефон и поднял уровни трассировки связанных элементов в /etc/bluetooth/bt_stack.conf

Успешное подключение - Первая попытка после перезагрузки телефона и установки приложения. Я могу подключиться, обнаружить все услуги / характеристики и читать / писать.

Неудачная попытка 1 - это следующая попытка после отключения от успешного подключения выше. Кажется, мне удалось обнаружить характеристики, но первая попытка чтения вернула нулевое значение и вскоре после этого отключилась.

Неудачная попытка 2 - пример, когда я даже не могу обнаружить услуги / характеристики.


РЕДАКТИРОВАТЬ 2:
устройство, к которому я пытаюсь подключиться, основано на микросхеме TI CC2541. Я получил TI SensorTag (также основанный на CC2541), чтобы поиграть с ним, и обнаружил, что TI выпустила приложение для Android для SensorTag вчера. Тем не менее, это приложение имеет ту же проблему. Я проверил это на двух других Nexus 4 с тем же результатом: подключение к SensorTag было успешным в первый или второй раз, но (согласно журналам) не удается обнаружить службы после этого, вызывая всевозможные сбои. Я начинаю удивляться, если это проблема с этим конкретным чипом?


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

3
Я использую Samsung Galaxy S4 с утечкой Google Edition Android 4.3; после многочисленных подключений / отключений, когда я обнаруживаю службы, я случайно получу 129 (GATT_INTERNAL_ERROR) и получу onConnectionStateChange со статусом 133 (GATT_ERROR), состояние = BluetoothProfile.DEVICE_DISCONNECTED.
13

1
Один или два раза за короткий промежуток времени я получал несколько обратных вызовов состояния 129 и 133, и я никогда не мог получить никакого обратного вызова в BluetoothGattCallback, пока не перезагрузил свое устройство (но сканирование в порядке).
13

1
Не забудьте сказать, что я тестирую около десяти устройств, использующих чипы TI (извините, я не знаю их моделей) и одно устройство с чипами Nordic. Устройство с чипами Nordic никогда не сообщает об ошибке (хотя этого недостаточно, чтобы доказать, что проблема
связана с

1
Я могу подтвердить, что эта проблема все еще существует на Samsung Galaxy S5 ( версия G900VVRU2BOG5 и G900VVRU2BOA8 ). Если я удаляю данные из меню «Настройки»> «Диспетчер приложений» >> «Все» >> «Bluetooth» , он работает некоторое время
IronBlossom

Ответы:


184

Важные советы по реализации

(Возможно, некоторые из этих подсказок больше не нужны из-за обновлений ОС Android.)

  1. Некоторым устройствам, таким как Nexus 4 с Android 4.3, требуется более 45 секунд для подключения с использованием существующего экземпляра gatt . Обходной путь: Всегда закрывайте экземпляры gatt при отключении и создавайте свежий экземпляр gatt при каждом подключении.
  2. Не забудьте позвонить android.bluetooth.BluetoothGatt#close()
  3. Начните новую тему внутри, onLeScan(..) а затем подключитесь. Причина: BluetoothDevice#connectGatt(Context context, boolean autoConnect, BluetoothGattCallback callback)всегда происходит сбой, если LeScanCallback() {...}.onLeScan(BluetoothDevice device, int rssi, byte[] scanRecord)вызывается изнутри в одном и том же потоке на Samsung Galaxy S3 с Android 4.3 (по крайней мере, для сборки JSS15J.I9300XXUGMK6)
  4. Большинство устройств фильтруют рекламу
  5. Лучше не использовать android.bluetooth.BluetoothAdapter#startLeScan(UUID[] serviceUuids, LeScanCallback callback) этот параметр для фильтрации определенных идентификаторов UUID службы, поскольку в Samsung Galaxy S3 с Android 4.3 это полностью нарушается и в целом не работает для 128-битных UUID .
  6. Гатт всегда может обрабатывать одну команду за раз . Если несколько команд вызываются по порядку, одна из них отменяется из-за синхронного характера реализации gatt.
  7. Я часто вижу даже на современных устройствах с Android 5, что Wi-Fi мешает с Bluetooth и наоборот. В крайнем случае, отключите Wi-Fi, чтобы стабилизировать Bluetooth.

Учебник для начинающих

Хорошей отправной точкой для новичков может стать видеоурок: «Разработка приложений Bluetooth для Android» http://youtu.be/x1y4tEHDwk0

Описанная ниже проблема и способ ее устранения, вероятно, теперь исправлены обновлениями ОС

Обойти: я мог бы "стабилизировать" мое приложение, делая это ...

  1. Я предоставляю пользователю настройку «Перезагрузить Bluetooth». Если этот параметр включен, я перезагружаю Bluetooth в некоторых точках, которые указывают, что начало стека BLE становится нестабильным. Например, если startScan возвращает false. Хорошим моментом также может быть, если serviceDiscovery не работает. Я просто выключаю и включаю Bluetooth.
  2. Я предоставляю другую настройку «Отключить WiFi». Если этот параметр включен, мое приложение отключает Wi-Fi во время его работы (и затем снова включает его)

Эта работа основана на следующем опыте ...

  • Перезапуск Bluetooth помогает исправить проблемы с BLE в большинстве случаев
  • Если вы отключите Wi-Fi, стек BLE станет намного стабильнее. Тем не менее, он также отлично работает на большинстве устройств с включенным Wi-Fi.
  • Если вы отключите Wi-Fi, перезапуск Bluetooth полностью восстановит стек BLE без необходимости перезагрузки устройства в большинстве случаев.

33
Google, ты должен исправить это сейчас. Эта работа вокруг (я сделал плюс это, потому что это работает), смешна.
Крис Герберт

4
Иногда обнаружение службы завершается успешно с состоянием 0 (при условии отсутствия проблем), однако чтение характеристик даст значения NULL, потому что оно по сути не связано или характеристики не обнаружены (я вижу это в журнале: 11-01 18:37: 32.131: WARN / BluetoothGatt (20119): необработанное исключение: java.lang.NullPointerException)
Lo-Tan

2
@ Lo-Tan Я всегда проверяю после обнаружения услуги, если моя ожидаемая услуга включена. Вы также никогда не можете быть уверены, если обнаружение службы дает какой-либо результат. Иногда я не получаю обратного вызова. Поэтому я применил тайм-аут для обнаружения службы.
OneWorld

2
Мой опыт таков: Samsung S3 (4.3) успешно переподключился после закрытия клиента Gatt, как описано в пункте 2 выше; используя Nexus 4 & 7 (4.4.2) Я не смог восстановить соединение после разрыва соединения, даже перезапустив BL-адаптер, но через 2 мин его можно автоматически снова подключить
Константин Конопко,

1
Может ли кто-нибудь подтвердить, что android.bluetooth.BluetoothGatt может обрабатывать только одну ожидающую операцию GATT ЗА УСТРОЙСТВО , ЗА ПРОЦЕСС или ПЕРИОД (то есть: во всех процессах). Я предполагаю, что это ЗА УСТРОЙСТВО, но эта проблема настолько испорчена, что меня не удивит, если бы это было иначе. Если ограничение только на УСТРОЙСТВО, то ОС / Устройство, способное обрабатывать несколько одновременных операций, является доказательством того, что эта проблема вызвана слабой наивной реализацией в экземпляре BluetoothAdapter, которую ОС передает каждому процессу (который, как я предполагал, был единый на все процессы).
swooby

18

ВЫКЛЮЧЕНИЕ WIFI:

Я также могу подтвердить, что отключение WIFI делает Bluetooth 4.0 более стабильным, особенно в Google Nexus (у меня Nexus 7).

Эта проблема

является то, что приложение, которое я разрабатываю потребности как WIFI, так и постоянного сканирования Bluetooth LE . Так что отключение WIFI не было для меня вариантом.

Более того, я понял, что непрерывное сканирование Bluetooth LE может на самом деле разорвать соединение WIFI и сделать адаптер WIFI неспособным повторно подключиться к любой сети WIFI, пока не будет включено сканирование BLE. (Я не уверен насчет мобильных сетей и мобильного интернета).
Это определенно произошло на следующих устройствах:

  • Нексус 7
  • Motorola Moto G

Однако BLE сканирование с включенным WIFI показалось довольно стабильным:

  • Samsung S4
  • HTC One

Мой обходной путь

Я сканирую BLE в течение короткого промежутка времени 3-4 секунды, затем выключаю сканирование на 3-4 секунды . Затем снова включите.

  • Очевидно, я всегда выключаю сканирование BLE при подключении к устройству BLE.
  • Когда я отключаюсь от устройства, я перезагружаю BLE (выключите, а затем включите адаптер), чтобы сбросить стек перед тем, как снова начать сканирование.
  • Я также сбрасываю BLE при обнаружении servicesили characteristicsсбое.
  • Когда я получаю рекламные данные с устройства, к которому должно подключиться приложение (скажем, 500 раз без возможности подключения - это около 5-10 секунд рекламы), я снова сбрасываю BLE.

Вы сказали, что я перезагружаю BLE после отключения устройства. Предположим, если пользователь передавал файл через соединение Bluetooth. Затем, Вы будете вызывать сбой передачи Bluetooth в любое время.
Рахул Растоги

1
что вы подразумеваете под "выключить адаптер и затем включить"?
Marian Paździoch

Я согласен, что Wi-Fi и Bluetooth вместе убивают производительность приложения в Moto G.
Нигилан

@ MarianPaździoch, «выключить и снова включить адаптер» @ benka означает BluetoothAdapter
Anup

9

Убедитесь, что ваш Nexus подключен к устройству. Я не могу проверить, работает ли связь должным образом, но вы сможете подключиться более одного раза без перезагрузки. Кажется, что первое соединение не требует сопряжения, но все последующие попытки делают.

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

РЕДАКТИРОВАТЬ: Оказывается, я тестировал версию встроенного программного обеспечения (наш датчик), который вызывал проблемы, если не было сопряжено. Наша последняя сборка серийной прошивки прекрасно работает на 2540-х и 2541-х годах.

РЕДАКТИРОВАТЬ: я заметил, что на Nexus 7 2013, соединения более стабильны, когда WiFi выключен. Я хотел бы знать, помогает ли это кому-нибудь еще.

РЕДАКТИРОВАТЬ: Кажется, я имел это задом наперед с сопряжением. Все отлично работает, когда не в паре. После сопряжения я испытываю те же симптомы, что и ОП. Пока неизвестно, связано ли это с нашей прошивкой или Android BLE API. Будьте внимательны при тестировании этого, потому что после сопряжения вы не сможете разорвать связь из-за ошибки, описанной в 3b этого поста .


Я постоянно подключаюсь и переподключаюсь к устройству CC2541 без какого-либо ручного сопряжения или перезагрузки.
dgel

На мой взгляд, нет необходимости в сопряжении. Официальные документы также не комментируют сопряжение. Я также мог бы выполнять запись, чтение, уведомление об изменении характеристики без сопряжения. Впрочем, ненадолго. Теперь опять шатко ... SAMSUNG BLE SKD v2.0 также не требует сопряжения и работает довольно хорошо.
OneWorld

3
Я могу подтвердить, что он более стабилен после отключения Wifi. Все должны попробовать это.
OneWorld,

1
Требуется ли сопряжение или нет, зависит от реализации устройства. Устройства nrf8002 требуют сопряжения, и Samsung 2.0 и 1.2 API поддерживают это. Похоже, что у официальной поддержки API есть проблемы с сопряжением, так как после того, как я подключу устройство, кажется, невозможно разорвать связь!
Крис Герберт

2
У меня есть работа из-за того, что я не могу разорвать отношения. 1) Зайдите в меню bt, выберите unpair, удалите устройство ble из области или отключите его, выберите устройство ble в меню bt, и оно попытается выполнить сопряжение и произойдет сбой, а затем сбросьте настройки Bluetooth. После сброса устройство будет непарным.
Крис Герберт

7

В некоторых моделях есть дефект: https://code.google.com/p/android/issues/detail?id=180440

С другой стороны, в моем случае проблема заключалась в том, что мое соединение не было правильно закрыто в методе onDestroy. После корректного закрытия проблема для меня не существует, не важно, включен или выключен вайфай.

btGatt.disconnect();
btGatt.close();

Зачем это closeнужно?
Игорь Ганапольский

3
Правильная процедура закрытия - это ключ, если вы хотите подключить Bluetooth несколько раз. По моему опыту, это работает лучше всего, если вы запускаете ваше соединение Ble в отдельной службе UNBOUND, чтобы вы могли запускать и останавливать его вручную. И что вы вызываете mConnectedGatt.disconnect (); ble_device = NULL; в вашем inDestroy (). В моем случае этот шаблон работает стабильно без проблем.
медтехника

4

Я столкнулся с аналогичной проблемой. Мое исправление было

if (Build.VERSION.SDK_INT >= 23) {
  mBluetoothGatt = device.connectGatt(this, false, mGattCallback, BluetoothDevice.TRANSPORT_LE);
} else {
  mBluetoothGatt = device.connectGatt(this, false, mGattCallback);
}

& звонить закрыть после отключения.

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