Android 4.3 Bluetooth Low Energy không ổn định


189

Tôi hiện đang phát triển một ứng dụng sẽ sử dụng Bluetooth Low Energy (thử nghiệm trên Nexus 4). Sau khi bắt đầu với API BLE chính thức trong Android 4.3, tôi nhận thấy rằng sau khi tôi kết nối thiết bị lần đầu tiên, tôi hiếm khi có thể kết nối thành công / giao tiếp với thiết bị đó hoặc bất kỳ thiết bị nào khác.

Theo hướng dẫn ở đây , tôi có thể kết nối thành công với một thiết bị, quét các dịch vụ và đặc điểm và đọc / ghi / nhận thông báo mà không gặp sự cố nào. Tuy nhiên, sau khi ngắt kết nối và kết nối lại, tôi thường không thể quét các dịch vụ / đặc điểm hoặc không thể hoàn thành việc đọc / ghi. Tôi không thể tìm thấy bất cứ điều gì trong nhật ký để cho biết tại sao điều này xảy ra.

Khi điều này xảy ra, tôi phải gỡ cài đặt ứng dụng, tắt Bluetooth và khởi động lại điện thoại trước khi ứng dụng bắt đầu hoạt động trở lại.

Bất cứ khi nào một thiết bị bị ngắt kết nối, tôi đảm bảo gọi close () trên đối tượng BluetoothGatt và đặt thành null. Bất kỳ hiểu biết?


EDIT: Bản
ghi nhật ký: Đối với những bản ghi này, tôi đã root điện thoại của mình và tăng mức độ theo dõi của các mục liên quan trong /etc/bluetooth/bt_stack.conf

Kết nối thành công - Lần thử đầu tiên sau khi khởi động lại điện thoại và cài đặt ứng dụng. Tôi có thể kết nối, khám phá tất cả các dịch vụ / đặc điểm và đọc / ghi.

Thất bại 1 - Đây là lần thử tiếp theo sau khi ngắt kết nối thành công ở trên. Có vẻ như tôi đã có thể khám phá các đặc điểm, nhưng lần thử đầu tiên để đọc đã trả về giá trị null và bị ngắt kết nối ngay sau đó.

Thất bại 2 - Một ví dụ mà tôi thậm chí không thể khám phá các dịch vụ / đặc điểm.


EDIT 2:
Thiết bị mà tôi đang cố gắng kết nối dựa trên chip CC2541 của TI. Tôi đã nhận được TI SensorTag (cũng dựa trên CC2541) để chơi xung quanh và phát hiện ra rằng TI đã phát hành một ứng dụng Android cho SensorTag ngày hôm qua. Tuy nhiên, ứng dụng này có cùng một vấn đề. Tôi đã thử nghiệm điều này trên hai chiếc Nexus 4 khác với cùng kết quả: Kết nối với SensorTag thành công lần đầu hoặc lần thứ hai, nhưng (theo nhật ký) không phát hiện ra các dịch vụ sau đó, gây ra tất cả các sự cố. Tôi bắt đầu tự hỏi liệu đó có phải là vấn đề với con chip cụ thể này không?


Vui lòng đăng nhật ký đầy đủ của điện thoại của bạn từ khi khởi động cho đến khi bạn đối mặt với vấn đề.
AAnkit

3
Tôi đang sử dụng Samsung Galaxy S4 đã cài đặt phiên bản Android 4.3 bị rò rỉ; sau nhiều thời gian kết nối / ngắt kết nối, khi tôi khám phá các dịch vụ, tôi sẽ nhận được ngẫu nhiên 129 (GATT_INTERNAL_ERROR) và nhận được onConnectionStateChange với trạng thái 133 (GATT_ERROR), state = BluetoothProfile.DEVICE_DISCONNECTED.
reTs

1
Trong một hoặc hai lần, tôi nhận được nhiều trạng thái gọi lại 129 và 133 trong một khoảng thời gian ngắn và tôi không bao giờ có thể nhận được bất kỳ cuộc gọi lại nào trong BluetoothGattCallback cho đến khi tôi khởi động lại thiết bị của mình (nhưng quét vẫn ổn).
reTs

1
Quên nói rằng tôi đang thử nghiệm với khoảng mười thiết bị sử dụng chip TI (xin lỗi tôi không biết mô hình của chúng) và một thiết bị có chip Bắc Âu. Thiết bị có chip Bắc Âu không bao giờ báo lỗi. (Tuy nhiên, không đủ để chứng minh sự cố là TI cụ thể)
reTs

1
Tôi có thể khẳng định rằng vấn đề này vẫn còn tồn tại trên Samsung Galaxy S5 (Cả hai G900VVRU2BOG5G900VVRU2BOA8 xây dựng phiên bản). Nếu tôi xóa dữ liệu khỏi Cài đặt> Trình quản lý ứng dụng >> Tất cả >> Bluetooth , nó sẽ hoạt động trong một thời gian.
IronBlieo

Câu trả lời:


184

Gợi ý thực hiện quan trọng

(Có lẽ một số gợi ý đó không còn cần thiết nữa do cập nhật hệ điều hành Android.)

  1. Một số thiết bị như Nexus 4 với Android 4.3 mất hơn 45 giây để kết nối bằng cách sử dụng phiên bản gatt hiện có . Làm việc xung quanh: Luôn đóng các trường hợp gatt khi ngắt kết nối và tạo một thể hiện mới của gatt trên mỗi kết nối.
  2. Đừng quên gọi android.bluetooth.BluetoothGatt#close()
  3. Bắt đầu một chủ đề mới bên trong onLeScan(..) và sau đó kết nối. Lý do: BluetoothDevice#connectGatt(Context context, boolean autoConnect, BluetoothGattCallback callback)luôn thất bại, nếu được gọi bên LeScanCallback() {...}.onLeScan(BluetoothDevice device, int rssi, byte[] scanRecord)trong cùng một luồng trên Samsung Galaxy S3 với Android 4.3 (ít nhất là để xây dựng JSS15J.I9300XXUGMK6)
  4. Hầu hết các thiết bị lọc quảng cáo
  5. Tốt hơn không nên sử dụng android.bluetooth.BluetoothAdapter#startLeScan(UUID[] serviceUuids, LeScanCallback callback) với tham số để lọc cho một số UUID dịch vụ nhất định vì điều này bị hỏng hoàn toàn trong Samsung Galaxy S3 với Android 4.3 và nói chung không hoạt động đối với các UUID 128 bit nói chung.
  6. Gatt luôn có thể xử lý một lệnh tại một thời điểm . Nếu một số lệnh được gọi ngắn sau lệnh khác, lệnh đầu tiên sẽ bị hủy do tính chất đồng bộ của việc thực hiện gatt.
  7. Tôi thường thấy ngay cả trên các thiết bị hiện đại có Android 5, rằng Wifi can thiệp vào bluetooth và ngược lại. Như một phương sách cuối cùng, tắt wifi để ổn định bluetooth.

Hướng dẫn cho người mới bắt đầu

Một điểm khởi đầu khá OK cho người mới có thể là video hướng dẫn này: Phát triển ứng dụng thông minh Bluetooth cho Android http://youtu.be/x1y4tEHDwk0

Vấn đề và giải quyết xung quanh được mô tả dưới đây có thể được khắc phục bằng các bản cập nhật hệ điều hành

Làm việc xung quanh: Tôi có thể "ổn định" ứng dụng của mình làm điều đó ...

  1. Tôi cung cấp cho người dùng cài đặt "Khởi động lại Bluetooth". Nếu cài đặt đó được bật, tôi khởi động lại Bluetooth tại một số điểm cho biết bắt đầu ngăn xếp BLE trở nên không ổn định. Ví dụ: nếu startScan trả về false. Một điểm tốt cũng có thể là nếu dịch vụ Khám phá thất bại. Tôi chỉ tắt và bật Bluetooth.
  2. Tôi cung cấp một cài đặt khác "Tắt WiFi". Nếu cài đặt đó được bật, ứng dụng của tôi sẽ tắt Wifi khi ứng dụng đang chạy (và bật lại sau đó)

Công việc này dựa trên kinh nghiệm theo dõi ...

  • Khởi động lại Bluetooth giúp khắc phục sự cố với BLE trong hầu hết các trường hợp
  • Nếu bạn tắt Wifi, ngăn xếp BLE sẽ ổn định hơn nhiều. Tuy nhiên, nó cũng hoạt động tốt trên hầu hết các thiết bị có bật wifi.
  • Nếu bạn tắt Wifi, khởi động lại Bluetooth sẽ phục hồi hoàn toàn ngăn xếp BLE mà không cần phải khởi động lại thiết bị trong hầu hết các trường hợp.

33
Google, bạn phải sửa cái này ngay bây giờ. Công việc này xung quanh (tôi đã làm cộng với nó bởi vì nó hoạt động) là vô lý.
Chris Herbert

4
Đôi khi, khám phá dịch vụ sẽ thành công với trạng thái 0 (giả sử không có vấn đề gì), nhưng các lần đọc đặc trưng sẽ mang lại giá trị NULL vì về cơ bản nó không thực sự được kết nối hoặc các đặc điểm không được phát hiện (tôi thấy điều này trong nhật ký: 11-01 18:37: 32.131: WARN / BluetoothGatt (20119): Ngoại lệ chưa được xử lý: java.lang.NullPulumException)
Lo-Tan

2
@ Lo-Tan Tôi luôn kiểm tra sau khi phát hiện dịch vụ, nếu dịch vụ dự kiến ​​của tôi được bao gồm. Bạn cũng không bao giờ có thể chắc chắn, nếu khám phá dịch vụ cho bất kỳ kết quả nào. Đôi khi tôi không nhận được cuộc gọi lại. Vì vậy, tôi đã áp dụng một thời gian chờ cho khám phá dịch vụ.
OneWorld

2
Kinh nghiệm của tôi là: Samsung S3 (4.3) đã kết nối lại thành công sau khi đóng ứng dụng khách Gatt như mô tả trong đoạn 2 ở trên; sử dụng Nexus 4 & 7 (4.4.2) Tôi không thể kết nối lại sau khi ngắt kết nối, ngay cả khi khởi động lại bộ chuyển đổi BL, nhưng nó có thể được kết nối lại tự động sau 2 phút
Konstantin Konopko

1
Bất cứ ai cũng có thể xác nhận nếu android.bluetooth.BluetoothGatt chỉ có thể xử lý một hoạt động GATT đang chờ xử lý PER DEVICE , PER PROCESS hoặc PERIOD (nghĩa là: trên tất cả các quy trình). Tôi đoán đó là PER DEVICE, nhưng vấn đề này được giải quyết đến mức nó sẽ không làm tôi ngạc nhiên nếu nó khác. Nếu giới hạn chỉ là PER DEVICE, thì HĐH / Thiết bị có thể xử lý nhiều hoạt động đồng thời là bằng chứng hút thuốc rằng vấn đề này hoàn toàn là do một số triển khai ngây thơ yếu trong phiên bản BluetoothAd CHƯƠNG mà HĐH xử lý từng quy trình (mà tôi đã giả định là một singleton trên tất cả các quy trình).
swooby 22/03/2016

18

TẮT WIFI:

Tôi cũng có thể xác nhận rằng việc bật WIFI OFF giúp Bluetooth 4.0 ổn định hơn, đặc biệt là trên Google Nexus (tôi có Nexus 7).

Vấn đề

là ứng dụng tôi đang phát triển cần cả WIFIquét Bluetooth LE liên tục . Vì vậy, tắt WIFI OFF không phải là lựa chọn cho tôi.

Ngoài ra, tôi đã nhận ra rằng quét Bluetooth LE liên tục thực sự có thể giết chết kết nối WIFI và khiến bộ điều hợp WIFI không thể kết nối lại với bất kỳ mạng WIFI nào cho đến khi quét BLE được BẬT. (Tôi không chắc chắn về mạng di động và internet di động).
Điều này chắc chắn đã xảy ra trên các thiết bị sau:

  • Nexus 7
  • Motorola Moto G

Tuy nhiên, quét BLE với WIFI trên có vẻ khá ổn định trên:

  • Samsung S4
  • HTC One

Cách giải quyết của tôi

Tôi quét BLE trong một khoảng thời gian ngắn 3-4 giây sau đó tôi tắt quét TẮT trong 3-4 giây . Sau đó BẬT lại.

  • Rõ ràng là tôi luôn TẮT quét BLE khi tôi kết nối với thiết bị BLE.
  • Khi tôi ngắt kết nối với thiết bị, tôi khởi động lại BLE (TẮT bộ chuyển đổi rồi BẬT) để đặt lại ngăn xếp trước khi bắt đầu quét lại.
  • Tôi cũng thiết lập lại BLE khi phát hiện serviceshoặc characteristicsthất bại.
  • Khi tôi nhận được dữ liệu quảng cáo từ một thiết bị mà ứng dụng sẽ kết nối (giả sử 500 lần mà không thể kết nối - đó là khoảng 5-10 giây quảng cáo), tôi đặt lại BLE một lần nữa.

Bạn nói tôi khởi động lại BLE sau khi thiết bị bị ngắt kết nối. Giả sử, nếu người dùng đang truyền tệp qua kết nối bluetooth. Sau đó, Bạn sẽ khiến việc chuyển bluetooth bị thất bại bất cứ lúc nào.
Rahul Rastogi

1
Ý bạn là gì khi "TẮT bộ chuyển đổi rồi BẬT"?
Mary Paździoch

Tôi đồng ý, Wifi và Bluetooth cùng nhau sẽ giết chết hiệu suất ứng dụng trong Moto G.
Nigilan 16/07/2015

@ MarianPaździoch, bằng cách "TẮT bộ chuyển đổi rồi BẬT" @ benka có nghĩa là BluetoothAd CHƯƠNG
Anup

9

Đảm bảo Nexus của bạn được ghép nối với thiết bị. Tôi không thể xác minh liệu giao tiếp có hoạt động đúng hay không, nhưng bạn sẽ có thể kết nối nhiều lần mà không cần khởi động lại. Có vẻ như kết nối đầu tiên không yêu cầu ghép nối nhưng tất cả các lần thử tiếp theo đều được.

Tôi sẽ cập nhật câu trả lời này trong một vài ngày khi tôi kiểm tra khám phá dịch vụ và gatt đọc và viết yêu cầu mà không cần khởi động lại.

EDIT: Hóa ra tôi đã thử nghiệm trên phiên bản phần mềm phát triển (cảm biến của chúng tôi) gây ra sự cố nếu không được ghép nối. Bản dựng firmware sản xuất mới nhất của chúng tôi hoạt động tốt vào những năm 2540 và 2541.

EDIT: Tôi đã nhận thấy rằng trên Nexus 7 2013, các kết nối ổn định hơn khi tắt WiFi. Tôi muốn biết nếu điều này giúp bất cứ ai khác.

EDIT: Tôi dường như đã có nó ngược với ghép nối. Mọi thứ hoạt động tốt khi không được ghép nối. Sau khi ghép nối, tôi gặp phải các triệu chứng chính xác giống như OP. Vẫn chưa biết nếu điều này có liên quan đến phần sụn của chúng tôi hoặc API BLE của Android. Hãy cẩn thận nếu kiểm tra điều này bởi vì một khi đã ghép nối, bạn có thể không hủy ghép nối do lỗi được giải thích trong 3b của bài đăng này .


Tôi liên tục kết nối và kết nối lại với thiết bị CC2541 mà không cần ghép nối thủ công hoặc khởi động lại.
dgel

Đối với ý kiến ​​của tôi, không có cặp đôi cần thiết. Các tài liệu chính thức không bình luận ghép đôi cũng. Tôi cũng có thể thực hiện ghi, đọc, thông báo thay đổi đặc tính mà không cần ghép nối. Tuy nhiên, chỉ trong một thời gian ngắn. Bây giờ nó lại rung lắc ... SAMSUNG BLE SKD v2.0 cũng không yêu cầu ghép nối và hoạt động khá tốt.
OneWorld

3
Tôi có thể xác nhận, nó ổn định hơn sau khi tắt Wifi. Mọi người nên thử điều đó.
OneWorld

1
Việc ghép nối có bắt buộc hay không phụ thuộc vào việc thực hiện thiết bị. Các thiết bị nrf8002 yêu cầu ghép nối và cả API của Samsung 2.0 và 1.2 đều hỗ trợ điều này. Có vẻ như hỗ trợ api chính thức đang gặp vấn đề với khía cạnh ghép nối vì sau khi tôi ghép nối một thiết bị ble, dường như không thể hủy ghép nối!
Chris Herbert

2
Tôi có một công việc xung quanh vì không thể hủy ghép nối. 1) vào menu bt của bạn, chọn hủy ghép nối, tháo thiết bị ble ra khỏi khu vực hoặc tắt thiết bị, chọn thiết bị ble trong menu bt và nó sẽ thử ghép nối và thất bại, sau đó đặt lại bluetooth. Sau khi thiết lập lại, thiết bị sẽ được ghép nối.
Chris Herbert

7

Trong một số mô hình có một lỗi: https://code.google.com.vn/p/android/issues/detail?id=180440

Mặt khác, trong trường hợp của tôi, vấn đề là, kết nối của tôi không được đóng đúng cách trong phương thức onDestroy. Sau khi đóng đúng, vấn đề đối với tôi không tồn tại, không quan trọng là bật hay tắt wifi.

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

Tại sao closecần thiết?
IgorGanapolsky

3
Quy trình đóng đúng là Khóa khi bạn muốn kết nối Bluetooth nhiều lần. Theo kinh nghiệm của tôi, nó hoạt động tốt nhất nếu bạn chạy kết nối Ble của mình trong dịch vụ UNBOUND riêng biệt để bạn có thể bắt đầu và dừng nó bằng tay. Và bạn gọi mConnectedGatt.disconnect (); ble_device = null; trong inDestroy () của bạn. Trong trường hợp của tôi mô hình này hoạt động ổn định mà không có vấn đề.
medTech

4

Tôi đã phải đối mặt với một vấn đề tương tự. Sửa chữa của tôi là

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

& gọi gần sau khi ngắt kết nối.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.