Khi sử dụng BluetoothAdapter
, bạn có thể tìm thấy các thiết bị Bluetooth từ xa thông qua tính năng phát hiện thiết bị hoặc bằng cách truy vấn danh sách thiết bị đã ghép nối.
Hãy đảm bảo bạn có quyền Bluetooth thích hợp và thiết lập ứng dụng của bạn cho Bluetooth trước khi tìm thiết bị Bluetooth.
Khám phá thiết bị là một quy trình quét tìm các thiết bị hỗ trợ Bluetooth trong phạm vi cục bộ và yêu cầu một số thông tin về từng thiết bị. Quá trình này đôi khi được gọi là khám phá, truy vấn hoặc quét. Thiết bị Bluetooth ở gần chỉ phản hồi yêu cầu khám phá nếu thiết bị đó đang chấp nhận các yêu cầu thông tin bằng cách có thể được khám phá. Nếu có thể phát hiện, thiết bị sẽ phản hồi yêu cầu khám phá bằng cách chia sẻ một số thông tin, chẳng hạn như tên thiết bị, lớp và địa chỉ MAC duy nhất của thiết bị. Bằng cách sử dụng thông tin này, thiết bị đang thực hiện quá trình khám phá có thể chọn bắt đầu kết nối với thiết bị đã khám phá.
Vì các thiết bị có thể khám phá có thể tiết lộ thông tin về vị trí của người dùng, nên quá trình khám phá thiết bị cần có quyền truy cập thông tin vị trí. Nếu ứng dụng của bạn đang được sử dụng trên một thiết bị chạy Android 8.0 (API cấp 26) trở lên, hãy cân nhắc sử dụng API Trình quản lý thiết bị đồng hành. API này thay mặt ứng dụng của bạn thực hiện việc khám phá thiết bị, vì vậy, ứng dụng của bạn không cần phải yêu cầu quyền truy cập thông tin vị trí.
Sau khi kết nối với thiết bị từ xa lần đầu tiên, yêu cầu ghép nối sẽ tự động hiển thị cho người dùng. Khi một thiết bị được ghép nối, thông tin cơ bản về thiết bị đó (chẳng hạn như tên, lớp và địa chỉ MAC của thiết bị) sẽ được lưu và có thể đọc được bằng API Bluetooth. Bằng cách sử dụng địa chỉ MAC đã biết cho một thiết bị từ xa, bạn có thể bắt đầu kết nối với thiết bị đó bất cứ lúc nào mà không cần thực hiện quá trình khám phá, giả sử thiết bị vẫn nằm trong phạm vi.
Xin lưu ý rằng có sự khác biệt giữa việc ghép nối và kết nối:
- Ghép nối có nghĩa là hai thiết bị nhận biết được sự tồn tại của nhau, có khoá liên kết dùng chung có thể dùng để xác thực và có khả năng thiết lập kết nối được mã hoá với nhau.
- Trạng thái kết nối có nghĩa là các thiết bị hiện đang chia sẻ một kênh RFCOMM và có thể truyền dữ liệu với nhau. Các API Bluetooth hiện tại yêu cầu thiết bị phải được ghép nối trước khi có thể thiết lập kết nối RFCOMM. Quá trình ghép nối sẽ tự động thực hiện khi bạn bắt đầu một kết nối được mã hoá bằng API Bluetooth.
Các phần sau đây mô tả cách tìm thiết bị đã ghép nối và cách khám phá thiết bị mới bằng tính năng khám phá thiết bị.
Truy vấn thiết bị đã ghép nối
Trước khi thực hiện việc khám phá thiết bị, bạn nên truy vấn tập hợp các thiết bị đã ghép nối để xem liệu thiết bị mong muốn đã được biết hay chưa. Để thực hiện việc này, hãy gọi getBondedDevices()
.
Thao tác này sẽ trả về một tập hợp các đối tượng BluetoothDevice
đại diện cho các thiết bị đã ghép nối. Ví dụ: bạn có thể truy vấn tất cả thiết bị đã ghép nối và lấy tên cũng như địa chỉ MAC của từng thiết bị, như minh hoạ trong đoạn mã sau:
Kotlin
val pairedDevices: Set<BluetoothDevice>? = bluetoothAdapter?.bondedDevices pairedDevices?.forEach { device -> val deviceName = device.name val deviceHardwareAddress = device.address // MAC address }
Java
Set<BluetoothDevice> pairedDevices = bluetoothAdapter.getBondedDevices(); if (pairedDevices.size() > 0) { // There are paired devices. Get the name and address of each paired device. for (BluetoothDevice device : pairedDevices) { String deviceName = device.getName(); String deviceHardwareAddress = device.getAddress(); // MAC address } }
Để bắt đầu kết nối với một thiết bị Bluetooth, tất cả những gì bạn cần từ đối tượng BluetoothDevice
được liên kết là địa chỉ MAC. Bạn truy xuất địa chỉ này bằng cách gọi getAddress()
. Bạn có thể tìm hiểu thêm về cách tạo kết nối trong phần Kết nối thiết bị Bluetooth.
Khám phá thiết bị
Để bắt đầu khám phá thiết bị, hãy gọi startDiscovery()
.
Quá trình này không đồng bộ và trả về một giá trị boolean cho biết liệu quá trình khám phá đã bắt đầu thành công hay chưa. Quá trình khám phá thường bao gồm một lượt quét truy vấn trong khoảng 12 giây, theo sau là một lượt quét trang của từng thiết bị được tìm thấy để truy xuất tên Bluetooth của thiết bị đó.
Để nhận thông tin về từng thiết bị được phát hiện, ứng dụng của bạn phải đăng ký BroadcastReceiver
cho ý định ACTION_FOUND
. Hệ thống sẽ truyền tin về ý định này cho từng thiết bị. Ý định này chứa các trường bổ sung EXTRA_DEVICE
và EXTRA_CLASS
, lần lượt chứa BluetoothDevice
và BluetoothClass
.
Đoạn mã sau đây cho biết cách bạn có thể đăng ký để xử lý thông báo truyền tin khi phát hiện thiết bị:
Kotlin
override fun onCreate(savedInstanceState: Bundle?) { ... // Register for broadcasts when a device is discovered. val filter = IntentFilter(BluetoothDevice.ACTION_FOUND) registerReceiver(receiver, filter) } // Create a BroadcastReceiver for ACTION_FOUND. private val receiver = object : BroadcastReceiver() { override fun onReceive(context: Context, intent: Intent) { val action: String = intent.action when(action) { BluetoothDevice.ACTION_FOUND -> { // Discovery has found a device. Get the BluetoothDevice // object and its info from the Intent. val device: BluetoothDevice = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE) val deviceName = device.name val deviceHardwareAddress = device.address // MAC address } } } } override fun onDestroy() { super.onDestroy() ... // Don't forget to unregister the ACTION_FOUND receiver. unregisterReceiver(receiver) }
Java
@Override protected void onCreate(Bundle savedInstanceState) { ... // Register for broadcasts when a device is discovered. IntentFilter filter = new IntentFilter(BluetoothDevice.ACTION_FOUND); registerReceiver(receiver, filter); } // Create a BroadcastReceiver for ACTION_FOUND. private final BroadcastReceiver receiver = new BroadcastReceiver() { public void onReceive(Context context, Intent intent) { String action = intent.getAction(); if (BluetoothDevice.ACTION_FOUND.equals(action)) { // Discovery has found a device. Get the BluetoothDevice // object and its info from the Intent. BluetoothDevice device = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE); String deviceName = device.getName(); String deviceHardwareAddress = device.getAddress(); // MAC address } } }; @Override protected void onDestroy() { super.onDestroy(); ... // Don't forget to unregister the ACTION_FOUND receiver. unregisterReceiver(receiver); }
Để bắt đầu kết nối với một thiết bị Bluetooth, bạn gọi getAddress()
trên BluetoothDevice
để truy xuất địa chỉ MAC được liên kết.
Tăng khả năng người dùng tìm thấy ứng dụng
Để các thiết bị khác có thể phát hiện thiết bị cục bộ, hãy gọi startActivityForResult(Intent, int)
bằng ý định ACTION_REQUEST_DISCOVERABLE
. Thao tác này sẽ đưa ra yêu cầu bật chế độ có thể phát hiện của hệ thống mà không cần chuyển đến ứng dụng Cài đặt. Thao tác này sẽ dừng ứng dụng của bạn. Theo mặc định, thiết bị sẽ có thể phát hiện trong hai phút. Bạn có thể xác định một thời lượng khác, tối đa là 5 phút, bằng cách thêm EXTRA_DISCOVERABLE_DURATION
bổ sung.
Đoạn mã sau đây đặt thiết bị ở chế độ có thể phát hiện trong 5 phút:
Kotlin
val requestCode = 1; val discoverableIntent: Intent = Intent(BluetoothAdapter.ACTION_REQUEST_DISCOVERABLE).apply { putExtra(BluetoothAdapter.EXTRA_DISCOVERABLE_DURATION, 300) } startActivityForResult(discoverableIntent, requestCode)
Java
int requestCode = 1; Intent discoverableIntent = new Intent(BluetoothAdapter.ACTION_REQUEST_DISCOVERABLE); discoverableIntent.putExtra(BluetoothAdapter.EXTRA_DISCOVERABLE_DURATION, 300); startActivityForResult(discoverableIntent, requestCode);
Hình 2: Hộp thoại bật khả năng tìm thấy.
Một hộp thoại sẽ hiển thị, yêu cầu người dùng cấp quyền để thiết bị có thể được phát hiện, như minh hoạ trong hình 2. Nếu người dùng trả lời "Cho phép", thì thiết bị sẽ có thể được phát hiện trong khoảng thời gian được chỉ định. Sau đó, hoạt động của bạn sẽ nhận được lệnh gọi đến lệnh gọi lại onActivityResult()
, với mã kết quả bằng với thời lượng mà thiết bị có thể được phát hiện. Nếu người dùng trả lời "Từ chối" hoặc nếu xảy ra lỗi, thì mã kết quả sẽ là RESULT_CANCELED
.
Thiết bị sẽ âm thầm ở chế độ có thể phát hiện trong khoảng thời gian được chỉ định. Để được thông báo khi chế độ có thể phát hiện thay đổi, hãy đăng ký BroadcastReceiver
cho ý định ACTION_SCAN_MODE_CHANGED
. Ý định này chứa các trường bổ sung EXTRA_SCAN_MODE
và EXTRA_PREVIOUS_SCAN_MODE
, cung cấp chế độ quét mới và cũ tương ứng. Các giá trị có thể có cho mỗi phần bổ sung như sau:
SCAN_MODE_CONNECTABLE_DISCOVERABLE
- Thiết bị đang ở chế độ phát hiện.
SCAN_MODE_CONNECTABLE
- Thiết bị không ở chế độ có thể phát hiện nhưng vẫn có thể nhận kết nối.
SCAN_MODE_NONE
- Thiết bị không ở chế độ có thể phát hiện và không thể nhận kết nối.
Nếu đang bắt đầu kết nối với một thiết bị từ xa, bạn không cần bật tính năng phát hiện thiết bị. Bạn chỉ cần bật tính năng khả năng khám phá khi muốn ứng dụng lưu trữ một ổ cắm máy chủ chấp nhận các kết nối đến, vì các thiết bị từ xa phải có thể khám phá các thiết bị khác trước khi bắt đầu kết nối với các thiết bị đó.