Android 4.3 Bluetooth з низьким рівнем енергії нестабільний


189

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

Дотримуючись тут інструкції , я можу успішно підключитися до пристрою, сканувати послуги та характеристики та читати / писати / отримувати сповіщення без проблем. Однак після відключення та повторного підключення я часто не можу сканувати послуги / характеристики або не можу завершити читання / запис. Я не можу знайти нічого в журналах, щоб вказати, чому це відбувається.

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

Кожен раз, коли відключений пристрій, я обов'язково дзвоню рядок () на об'єкт BluetoothGatt і встановлюю його на нуль. Будь-які уявлення?


Редагувати:
Log відвалів: Для цих журналів я корениться мій телефон і підвищив рівень трасування пов'язаних елементів в /etc/bluetooth/bt_stack.conf

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

Невдала спроба 1 спроби - це наступна спроба після відключення від успішного з'єднання вище. Здається, я зміг виявити характеристики, але перша спроба прочитати повернула нульове значення і незабаром після цього відключилася.

Помилка спроби 2 - Приклад, коли я навіть не в змозі виявити послуги / характеристики.


EDIT 2:
Пристрій, до якого я намагаюся підключитися, базується на мікросхемі TI CC2541. Я отримав TI SensorTag (також заснований на CC2541), щоб пограти з ним і виявив, що TI вчора випустив додаток для Android для SensorTag. Однак у цієї програми є та сама проблема. Я перевірив це на двох інших Nexus 4s з тим самим результатом: Підключення до SensorTag є успішним перший або другий раз, але (згідно з журналами) не вдається знайти сервіси після цього, викликаючи всілякі збої. Я починаю цікавитись, чи це проблема з цією конкретною мікросхемою?


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

3
Я використовую Samsung Galaxy S4 із встановленою версією Google Android Android 4.3; після численного часу підключення / відключення, коли я виявляю послуги, я випадково отримаю 129 (GATT_INTERNAL_ERROR) і отримаю onConnectionStateChange зі статусом 133 (GATT_ERROR), state = BluetoothProfile.DEVICE_DISCONNECTED.
реЦ

1
За один чи два рази я отримав декілька статусних 129 і 133 зворотних зворотних дзвінків за короткий проміжок часу, і я ніколи не міг отримати зворотного дзвінка в BluetoothGattCallback, поки не перезавантажую свій пристрій (але сканування нормально).
reTs

1
Забудьте сказати, що я тестую близько десяти пристроїв, що використовують мікросхеми TI (вибачте, я не знаю їхніх моделей) та один пристрій із скандинавськими мікросхемами. Пристрій із скандинавськими чіпами ніколи не повідомляє про помилки. (Недостатньо, щоб довести, що проблема є специфічною TI)
reTs

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 завжди може обробляти по одній команді за один раз . Якщо декілька команд викликаються коротко за іншою, перша скасовується через синхронний характер реалізації gatt.
  7. Я часто бачу навіть на сучасних пристроях з Android 5, що Wi-Fi заважає Bluetooth і навпаки. В крайньому випадку вимкніть wifi для стабілізації Bluetooth.

Підручник для початківців

Досить нормальною точкою входу для новачків може стати цей відеоурок: Розробка смарт-додатків Bluetooth для Android http://youtu.be/x1y4tEHDwk0

Описані нижче проблеми та вирішення проблеми, ймовірно, тепер вирішені оновленнями ОС

Подолання: я міг "стабілізувати" свій додаток, роблячи це ...

  1. Я надаю користувачу налаштування "Перезапустити Bluetooth". Якщо це налаштування увімкнено, я перезапускаю Bluetooth у деяких точках, які вказують на початок BLE-стека стає нестабільним. Наприклад, якщо startScan повертає значення false. Хороший момент може бути також, якщо serviceDiscovery failes. Я просто вимикаю і вмикаю Bluetooth.
  2. Я надаю ще одне налаштування "Вимкнути WiFi". Якщо цей параметр увімкнено, мій додаток вимикає Wi-Fi під час роботи програми (і знову вмикає його)

Ця робота базується на наступних враженнях ...

  • Перезапуск Bluetooth допомагає вирішити проблеми з BLE в більшості випадків
  • Якщо вимкнути Wi-Fi, стек BLE стає набагато стійкішим. Однак він також чудово працює на більшості пристроїв із увімкненим Wi-Fi.
  • Якщо вимкнути Wifi, перезапуск 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-сканування не буде включеним. (Я не впевнений у мобільних мережах та мобільному Інтернеті).
Це безумовно сталося на таких пристроях:

  • Nexus 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 через Bluetooth не зможе в будь-який час.
Рахул Растогі

1
що ви маєте на увазі під "вимкнути адаптер, а потім увімкнути"?
Marian Paździoch

Я згоден, Wifi та Bluetooth разом вбивають продуктивність програми в Moto G.
Nigilan

@ MarianPaździoch, "вимкніть адаптер, а потім увімкнено" @ benka означає BluetoothAdapter
Ануп

9

Переконайтесь, що ваш Nexus з'єднаний з пристроєм. Я не можу перевірити, чи працює зв’язок належним чином чи ні, але ви зможете підключитися не один раз без перезавантаження. Здається, для першого підключення не потрібно спарювання, але всі наступні спроби робити.

Цю відповідь я оновлю через пару днів, коли я перевіряю службове виявлення та матиму змогу читати та писати запити без перезавантаження.

EDIT: Виявляється, я тестував версію прошивки для розробки (наш датчик), яка викликала проблеми, якщо не спарені. Наша остання виробнича версія прошивки працює чудово в 2540-х і 2541-х.

EDIT: Я помітив, що в Nexus 7 2013 зв’язки стабільніші, коли WiFi вимкнено. Я хотів би знати, чи допомагає це комусь іншому.

EDIT: Я, здається, мав це назад із сполученням. Все працює добре, коли не працює в парі. Після спарювання я відчуваю такі самі симптоми, як і ОП. Просто поки невідомо, чи це пов’язано з нашою прошивкою або API BLE для Android. Будьте обережні, якщо тестувати це, тому що, спарившись, ви не зможете відключитись через помилку, пояснену в 3b цієї публікації .


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

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

3
Я можу підтвердити, це стабільніше після відключення Wi-Fi. Кожен повинен спробувати це.
OneWorld

1
Необхідність спарювання чи ні, залежить від реалізації пристрою. Пристрої nrf8002 вимагають створення пари, і Samsung 2.0 і 1.2 API підтримують це. Здається, що офіційна підтримка api має проблеми з аспектом сполучення, оскільки після того, як я спарюю пристрій, відключити його здається неможливо!
Кріс Герберт

2
У мене є робота над тим, що я не можу зняти з ладу. 1) перейдіть до свого меню Bt, виберіть відключення, вийміть пристрій ble з області або вимкніть його, виберіть пристрій ble в меню bt і воно спробує з'єднатись і вийти з ладу, а потім скиньте Bluetooth. Після скидання пристрій буде відключений.
Кріс Герберт

7

У деяких моделях є дефект: https://code.google.com/p/android/isissue/detail?id=180440

З іншого боку, в моєму випадку проблема полягала в тому, що мій зв’язок не був належним чином закритий у методі onDestroy. Після правильного закриття проблеми для мене не існує, незалежно від того, включений або вимкнений wifi.

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

Навіщо це closeпотрібно?
ІгорГанапольський

3
Правильна процедура закриття є Ключовою, коли потрібно підключити Bluetooth кілька разів. На мій досвід, це найкраще працює, якщо ви запускаєте з'єднання Ble в окремій службі UNBOUND, щоб ви могли запустити і зупинити його вручну. І що ви називаєте mConnectedGatt.disconnect (); ble_device = null; у вашому inDestroy (). У моєму випадку ця модель працює без проблем.
medTech

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.