Tìm thiết bị Bluetooth

Bằng cách sử dụng BluetoothAdapter, bạn có thể tìm các thiết bị Bluetooth từ xa thông qua tính năng khám phá thiết bị hoặc bằng cách để truy vấn danh sách thiết bị đã ghép nối.

Đảm bảo bạn có quyền truy cập Bluetooth thích hợp và thiết lập ứng dụng của bạn cho Bluetooth trước khi thử tìm thiết bị Bluetooth.

Khám phá thiết bị là một quy trình quét tìm kiếm trong khu vực cục bộ Thiết bị hỗ trợ Bluetooth và yêu cầu một số thông tin về từng thiết bị. Chiến dịch này quá trình đôi khi được gọi là khám phá, hỏi hoặc quét. Thiết bị Bluetooth ở gần chỉ phản hồi yêu cầu khám phá nếu yêu cầu đó là hiện đang chấp nhận yêu cầu cung cấp thông tin bằng cách tìm kiếm được. Nếu một thiết bị là tìm thấy, nó phản hồi yêu cầu khám phá bằng cách chia sẻ một số thông tin, như tên, lớp và địa chỉ MAC duy nhất của thiết bị. Đang dùng thì 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ị được phát hiện.

Vì thiết bị phát hiện được có thể tiết lộ thông tin về vị trí của người dùng, quá trình khám phá thiết bị yêu cầu 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 thiết bị chạy Android 8.0 (API cấp 26) trở lên, hãy cân nhắc sử dụng Trình quản lý thiết bị đồng hành API. 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 yêu cầu quyền truy cập thông tin vị trí.

Sau lần đầu kết nối với thiết bị từ xa, 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à MAC của thiết bị địa chỉ—được lưu và có thể đọc được bằng API Bluetooth. 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 bằng thiết bị đó bất kỳ lúc nào mà không thực hiện khám phá, giả sử thiết bị vẫn nằm trong phạm vi.

Lưu ý rằng có sự khác biệt giữa việc được ghép nối và đang được kết nối:

  • Được ghép nối có nghĩa là hai thiết bị biết về sự tồn tại của nhau, có một khoá liên kết dùng chung có thể dùng để xác thực và thiết lập kết nối được mã hoá với nhau.
  • Được kết nối có nghĩa là các thiết bị hiện dùng chung một kênh RFCOMM và có thể truyền dữ liệu với nhau. Bluetooth hiện tại API yêu cầu các thiết bị phải được ghép nối trước khi có thể kết nối RFCOMM thiết lập. Quá trình ghép nối sẽ tự động được thực hiện khi bạn bắt đầu quá trình mã hoá kết nối với API Bluetooth.

Các phần sau đây mô tả cách tìm thiết bị đã được 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 khám phá thiết bị, bạn nên truy vấn tập hợp các thiết bị để 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(). Hàm này sẽ trả về một tập hợp Đối tượng BluetoothDevice biểu thị các thiết bị đã ghép nối. Ví dụ: bạn có thể truy vấn mọi thiết bị đã ghép nối và lấy tên và địa chỉ MAC của từng thiết bị, như đoạn mã sau thể hiện:

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 thiết bị Bluetooth, tất cả những gì cần làm từ đối tượng BluetoothDevice được liên kết là địa chỉ MAC mà bạn truy xuất bằng đang gọi getAddress(). Bạn có thể tìm hiểu thêm về cách tạo kết nối trong bài viết Kết nối Bluetooth thiết bị.

Khám phá các thiết bị

Để bắt đầu khám phá các 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 khám phá đã bắt đầu thành công. Quá trình khám phá thường liên quan đến một quét yêu cầu trong khoảng 12 giây, sau đó quét từng thiết bị để 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 ACTION_FOUND ý định. Hệ thống sẽ truyền ý định này cho từng thiết bị. Ý định chứa các trường bổ sung EXTRA_DEVICEEXTRA_CLASS là lần lượt chứa BluetoothDevice và một BluetoothClass. Đoạn mã sau đây cho biết cách bạn có thể đăng ký để xử lý việc truyền tin khi thiết bị được phát hiện:

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.

Bật khả năng được phát hiện

Để các thiết bị khác có thể phát hiện được thiết bị cục bộ này, hãy gọi startActivityForResult(Intent, int) với ACTION_REQUEST_DISCOVERABLE ý định. 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 phải chuyển đến ứng dụng Cài đặt. Việc này sẽ khiến ứng dụng của bạn ngừng hoạt động. Theo Theo mặc định, thiết bị sẽ có thể phát hiện được trong 2 phút. Bạn có thể xác định thời lượng khác nhau, tối đa là 1 giờ, bằng cách thêm EXTRA_DISCOVERABLE_DURATION khác.

Đ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);

số
Hình 2: Hộp thoại bật khả năng phát hiện.

Một hộp thoại đang hiển thị, yêu cầu người dùng cho phép chế tạo thiết bị dễ tìm thấy, như được minh hoạ trong hình 2. Nếu người dùng trả lời "Cho phép", thì thiết bị có thể phát hiện được trong một khoảng thời gian nhất định. Sau đó, hoạt động của bạn nhận được một cuộc gọi đến onActivityResult() lệnh gọi lại, với mã kết quả bằng với thời lượng thiết bị có thể phát hiện. Nếu người dùng trả lời "Từ chối" hoặc nếu có lỗi xảy ra, thì kết quả có mã là RESULT_CANCELED.

Thiết bị sẽ ở chế độ im lặng ở chế độ có thể phát hiện trong thời gian quy định. Để trở thành thông báo khi chế độ phát hiện được thay đổi, hãy đăng ký BroadcastReceiver cho ACTION_SCAN_MODE_CHANGED ý định. Ý định này chứa các trường bổ sung EXTRA_SCAN_MODEEXTRA_PREVIOUS_SCAN_MODE, cung cấp chế độ quét mới và cũ tương ứng. Mỗi giá trị có thể có như sau:

SCAN_MODE_CONNECTABLE_DISCOVERABLE
Thiết bị đang ở chế độ có thể phát hiện.
SCAN_MODE_CONNECTABLE
Thiết bị không ở chế độ phát hiện được 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 khởi tạo kết nối với một thiết bị từ xa, bạn không cần cho phép khả năng phát hiện thiết bị. Bạn chỉ cần bật khả năng được phát hiện khi bạn muốn ứng dụng của mình lưu trữ một cổng máy chủ chấp nhận thư đến các kết nối, vì thiết bị từ xa phải có thể phát hiện ra các thiết bị khác trước bắt đầu kết nối với các thiết bị khác đó.