Computer >> Hướng Dẫn Máy Tính >  >> Hệ Thống >> Android

Tăng cường độ tin cậy của Bluetooth trên Android:Các mẹo đã được chứng minh để có kết nối nhất quán

Tăng cường độ tin cậy của Bluetooth trên Android:Các mẹo đã được chứng minh để có kết nối nhất quán

Bạn có thể đã từng gặp trường hợp này trước đây:tai nghe không dây của bạn kết nối hoàn hảo vào một ngày nào đó và ngày tiếp theo chúng hoạt động như thể chưa từng gặp điện thoại của bạn. Hoặc đồng hồ thông minh của bạn bị rơi khi đang chạy. Bluetooth thật tuyệt vời khi nó hoạt động nhưng thật khó chịu khi nó không hoạt động.

Tôi làm kỹ sư phần mềm Bluetooth trên các thiết bị đeo được như kính thông minh và tôi đã dành nhiều thời gian hơn mức tôi muốn thừa nhận để tìm hiểu lý do tại sao những thứ này lại hỏng.

Trong bài viết này, tôi sẽ cung cấp cho bạn một cái nhìn sâu sắc:cách hoạt động thực sự của ngăn xếp Bluetooth của Android, lý do đôi khi khiến bạn cảm thấy khó đoán và những gì bạn có thể làm với tư cách là nhà phát triển để giúp ứng dụng hoặc hệ thống của mình trở nên đáng tin cậy hơn.

Bluetooth bằng tiếng Anh đơn giản

Về cốt lõi, Bluetooth chỉ là cuộc trò chuyện giữa hai thiết bị. Nhưng đó không phải là một đường dây liên lạc đơn giản – nó có nhiều lớp xếp chồng lên nhau.

  • Đài (Bộ điều khiển): Gửi và nhận tín hiệu thực tế qua môi trường không khí.

  • Bộ não phần mềm (Ngăn xếp máy chủ): Quyết định nói chuyện với ai, nói chuyện như thế nào cũng như có muốn hay không.

  • Hồ sơ: Xác định mục đích của cuộc trò chuyện – chẳng hạn như phát nhạc trực tuyến hoặc đồng bộ hóa dữ liệu sức khỏe.

  • Giao thức: Xác định cách nói chuyện với thiết bị kia.

Có hai “hương vị” lớn của bluetooth:

  • Cổ điển (BR/EDR): Được sử dụng cho những thứ như tai nghe và bộ phụ kiện xe hơi. Có thể nâng tạ nặng hơn.

  • Năng lượng thấp (LE): Được sử dụng cho dây đeo thể dục, đèn hiệu và hầu hết các thiết bị đeo. Có thể duy trì lâu hơn.

Hầu hết các thiết bị hiện đại đều sử dụng cả hai cùng một lúc. Điều đó có tác dụng mạnh mẽ nhưng cũng mở ra cơ hội cho nhiều điều sai trái hơn.

Tại sao Android lại có những đặc điểm riêng

Tăng cường độ tin cậy của Bluetooth trên Android:Các mẹo đã được chứng minh để có kết nối nhất quán

Trên Android, Bluetooth không chỉ là một gói gọn gàng. Đó là một chuỗi các bộ phận chuyển động:

  • Ứng dụng của bạn gọi BluetoothAdapter .

  • Những thứ đó đi vào dịch vụ hệ thống như AdapterService .

  • Sau đó vào mã gốc thông qua JNI (Giao diện gốc Java).

  • Sau đó vào ngăn xếp Bluetooth của nhà cung cấp chip .

  • Cuối cùng, nó chạm tới phần cứng vô tuyến .

Mỗi nhà sản xuất điện thoại đều cung cấp một chip Bluetooth và chương trình cơ sở hơi khác nhau. Điều đó có nghĩa là cùng một ứng dụng Bluetooth có thể hoạt động khác nhau trên Samsung, Pixel hoặc bất kỳ điện thoại giá rẻ nào khác chạy Android.

Vấn đề thực sự đằng sau “Nó vừa bị ngắt kết nối”

Dưới đây là một số cơn đau đầu phổ biến mà tôi gặp, được giải thích đơn giản:

Vấn đề liên kết (vấn đề “mất chìa khóa”)

Khi hai thiết bị Bluetooth ghép nối, chúng sẽ trao đổi khóa mã hóa (khóa liên kết cho Khóa cổ điển, Khóa dài hạn cho LE) và lưu trữ chúng trong bộ nhớ cố định. Các khóa này giúp các thiết bị nhận ra nhau sau này và kết nối lại an toàn mà không cần hỏi lại người dùng.

Sự cố "bộ nhớ không khớp" xảy ra khi khóa được lưu trữ của một thiết bị không khớp với khóa của thiết bị kia nữa. Điều này có thể do:

  • Bản cập nhật chương trình cơ sở hoặc bản nâng cấp hệ điều hành có chức năng xóa hoặc tạo lại khóa.

  • Một bên là khôi phục cài đặt gốc hoặc "quên thiết bị" nhưng bên kia thì không.

  • Các khóa bị lỗi hoặc bị hệ thống xóa để giải phóng bộ nhớ.

Từ góc độ của người dùng, thiết bị vẫn có thể xem đã ghép nối (hiển thị trong menu Bluetooth) nhưng các kết nối không thành công một cách bí ẩn với các lỗi như “Xác thực không thành công” hoặc “Mã hóa không đủ”. Cách chữa trị duy nhất thường là xóa thiết bị ở cả hai đầu và ghép nối lại, điều này khiến người dùng không rành về kỹ thuật cảm thấy vô lý.

Thời gian không khớp

Các thiết bị Bluetooth không chỉ trò chuyện bất cứ khi nào họ muốn, chúng còn thống nhất về khoảng thời gian kết nối – về cơ bản là lịch trình khi mỗi bên sẽ “thức dậy” và trao đổi gói tin. Hãy nghĩ về việc hai người đồng ý gặp nhau 30 phút một lần tại quán cà phê.

Sự không khớp xảy ra khi:

  • Hai bên thương lượng các khoảng thời gian khác nhau nhưng không hoàn toàn thống nhất (ví dụ, một bên cho rằng là 30ms, bên kia cho là 50ms).

  • Cập nhật chương trình cơ sở hoặc thay đổi cấu hình của một bên sẽ thay đổi chính sách thời gian của bên đó.

  • Điều kiện vô tuyến khiến một bên bỏ lỡ nhiều lần đăng ký theo lịch trình, làm lệch đồng hồ.

  • Logic tiết kiệm năng lượng (giống như điện thoại chuyển sang chế độ Doze) âm thầm kéo dài khoảng thời gian.

Điều này giải thích tại sao kết nối có thể hoạt động tốt lúc đầu nhưng sau đó bắt đầu không thành công:ban đầu các thiết bị được đồng bộ hóa trong một khoảng thời gian, nhưng sau đó chính sách hoặc hành vi của một bên đã thay đổi. Từ góc nhìn của người dùng, có vẻ như âm thanh bị giật, đầu vào bị lag (trên bộ điều khiển trò chơi) hoặc ngắt kết nối ngẫu nhiên sau khi “trước đây nó vẫn hoạt động tốt”.

Ngắt kết nối không mong muốn

Khi liên kết Bluetooth kết thúc, lớp vô tuyến (bộ điều khiển) và ngăn xếp hệ điều hành cấp cao hơn (máy chủ) có nhiệm vụ trao đổi tín hiệu rõ ràng. Bộ điều khiển gửi sự kiện Hoàn tất ngắt kết nối HCI (về cơ bản:“Tạm biệt, chúng ta đã hoàn tất” ). Sau đó, máy chủ sẽ cập nhật trạng thái bên trong, dọn sạch phiên GATT/ACL và sẵn sàng kết nối lại.

Nhưng trên thực tế, điều này không phải lúc nào cũng đúng:

  • Đôi khi bộ điều khiển nói lời tạm biệt một cách rõ ràng nhưng ngăn xếp máy chủ không cập nhật trạng thái của nó đúng cách. Ứng dụng vẫn "nghĩ" kết nối đang hoạt động nên các nỗ lực kết nối lại đều không thành công.

  • Một số nền tảng tích cực lưu vào bộ nhớ đệm trạng thái kết nối (đặc biệt là iOS). Nếu hệ điều hành cho rằng kết nối vẫn hợp lệ thì hệ điều hành sẽ không kích hoạt nỗ lực kết nối mới cho đến khi bạn bật Bluetooth hoặc khởi động lại.

  • Tình trạng tương tranh có thể xảy ra nếu sự kiện ngắt kết nối xảy ra trong khi một hoạt động khác (ví dụ:khám phá dịch vụ, liên kết hoặc thiết lập mã hóa) đang diễn ra. Hệ điều hành có thể nhầm lẫn về trạng thái của thiết bị thực sự trong.

  • Trên một số thiết bị, nỗ lực kết nối lại nhanh sau khi ngắt kết nối hoàn toàn sẽ va chạm với bộ hẹn giờ hồi chiêu bên trong. Bộ điều khiển bỏ qua nó, để ứng dụng chờ.

Ở góc độ người dùng, thiết bị trông có vẻ “bị kẹt”. Cách duy nhất để khôi phục là bật Bluetooth, khởi động lại ứng dụng hoặc cấp nguồn cho phụ kiện, mặc dù về mặt kỹ thuật không có gì "thất bại".

Cách nhà phát triển có thể làm tốt hơn

Nếu bạn đang xây dựng một ứng dụng Bluetooth thì sau đây là một số thói quen giúp bạn giảm bớt nhiều khó khăn:

Trước tiên hãy kiểm tra các thiết bị được ngoại quan

Một trong những nguyên nhân phổ biến nhất khiến kết nối không thành công là thông tin liên kết không khớp:điện thoại và phụ kiện không còn dùng chung khóa mã hóa. Ngay cả khi thiết bị xuất hiện trong giao diện người dùng, hệ điều hành có thể đã bị mất khóa.

Trước khi thử kết nối, hãy luôn truy vấn danh sách thiết bị ngoại quan của hệ thống bằng BluetoothAdapter.getBondedDevices() . Ví dụ:

if (adapter.getBondedDevices().contains(targetDevice)) {
 targetDevice.connectGatt(context, false, gattCallback);
} else {
 showToast("Please re-pair this device to restore the connection.");
}

Điều này đảm bảo bạn chỉ thử kết nối an toàn với các thiết bị mà hệ điều hành vẫn tin cậy. Nếu thiết bị mục tiêu không có trong danh sách liên kết, bạn có thể hướng dẫn rõ ràng cho người dùng (“Vui lòng ghép nối lại thiết bị này”) thay vì để lại cho họ những lỗi kết nối khó hiểu.

Xử lý lệnh gọi lại một cách cẩn thận

Một cạm bẫy tinh vi khác là giả định rằng STATE_CONNECTED sự kiện có nghĩa là kết nối đã thành công. Trên thực tế, onConnectionStateChange() có thể báo cáo trạng thái được kết nối ngay cả khi thao tác cơ bản không thành công, kết quả thực sự là ở status lý lẽ. Để tránh truy đuổi các kết nối ảo, hãy luôn kiểm tra cả statusnewState :

if (status == BluetoothGatt.GATT_SUCCESS &&
 newState == BluetoothProfile.STATE_CONNECTED) {
 gatt.discoverServices();
} else {
 gatt.close();
}

Mẫu này ngăn bạn cố gắng khám phá dịch vụ trên kết nối không hoạt động và đảm bảo các phiên cũ được đóng lại kịp thời, để ngăn xếp sẵn sàng cho lần thử lại sạch sẽ.

Mong đợi thất bại

Kết nối Bluetooth trong thế giới thực luôn bị lỗi – các thiết bị nằm ngoài phạm vi phủ sóng, nhiễu tăng đột biến ở băng tần 2,4 GHz hoặc đơn giản là sóng radio đang bận. Điều tồi tệ nhất mà một ứng dụng có thể làm là thử lại ngay lập tức trong một vòng lặp chặt chẽ, điều này làm hao pin và khiến ngăn xếp không ổn định.

Một cách tiếp cận tốt hơn là triển khai phương pháp rút lui theo cấp số nhân như thế này:

long delay = (long) Math.min(250 * Math.pow(2, attempt), 30000);
new Handler(Looper.getMainLooper()).postDelayed(connectAction, delay);

Điều này có nghĩa là lần thử lại đầu tiên của bạn diễn ra nhanh chóng (~250 mili giây), nhưng những lần thử lại tiếp theo sẽ chậm lại (500 mili giây, 1 giây, 2 giây…), giới hạn ở mức tối đa hợp lý. Backoff giúp ứng dụng của bạn có khả năng hoạt động linh hoạt mà không làm quá tải radio hoặc hệ điều hành.

Sử dụng đúng công cụ

Nếu không có khả năng hiển thị những gì đang diễn ra bên trong, các sự cố kết nối sẽ có vẻ ngẫu nhiên. Các công cụ như nRF Connect cho phép bạn quét, kết nối và chạy các hoạt động GATT trên thiết bị của mình một cách tương tác, trong khi nhật ký theo dõi Bluetooth HCI của Android hiển thị các gói thực tế được trao đổi. Ví dụ:

Settings.Secure.putInt(context.getContentResolver(), "bluetooth_hci_log", 1);

Sau khi được bật, bạn có thể ghi lại dấu vết logcat và xác nhận xem lỗi có phải do thiếu khóa hay không (Insufficient Authentication ), thời gian không khớp hoặc bị nhiễu. Việc sử dụng những công cụ này không chỉ giúp bạn gỡ lỗi ứng dụng mà còn chứng minh liệu sự cố nằm ở mã, hệ điều hành hay chương trình cơ sở phụ kiện hay không.

Tăng cường độ tin cậy của Bluetooth trên Android:Các mẹo đã được chứng minh để có kết nối nhất quán

Bài học lớn hơn

Làm việc với Bluetooth đã dạy cho tôi những bài học áp dụng cho kỹ thuật nói chung:

  • Mạng không dây không bao giờ hoàn hảo, vì vậy, hãy luôn lưu ý đến việc xây dựng tính năng phục hồi.

  • Nhật ký và số liệu không phải là tùy chọn. Chúng là bản đồ giúp bạn vượt qua sự hỗn loạn.

  • Giải pháp đơn giản nhất thường tồn tại tốt nhất trong thế giới thực hỗn loạn.

Kết luận

Bluetooth rất lộn xộn vì nó là một chuỗi gồm phần cứng, chương trình cơ sở và phần mềm, tất cả đều cố gắng hợp tác với nhau. Trên Android, sự đa dạng của chip và nhà cung cấp khiến việc này thậm chí còn phức tạp hơn.

Nhưng điều đó không có nghĩa là bạn bất lực. Bằng cách hiểu cách hoạt động của các lớp và thiết kế ứng dụng của bạn bằng các lần thử lại, kiểm tra và ghi nhật ký thích hợp, bạn có thể làm cho Bluetooth bớt “kỳ lạ” hơn đối với người dùng của mình.

Lần tới khi tai nghe của bạn hoạt động sai, bạn sẽ biết – đó không phải là do bạn. Bluetooth chỉ là Bluetooth thôi.

Đây là bài đầu tiên trong số nhiều bài tôi sắp viết về quá trình phát triển Bluetooth. Trong phần tiếp theo, chúng ta sẽ tìm hiểu sâu hơn về cách xây dựng máy khách và máy chủ GATT Bluetooth Low Energy (BLE) an toàn trên Android. Hãy theo dõi!

Học cách viết mã miễn phí. Chương trình giảng dạy mã nguồn mở của freeCodeCamp đã giúp hơn 40.000 người có được việc làm với tư cách là nhà phát triển. Bắt đầu