ค้นหาอุปกรณ์บลูทูธ

เมื่อใช้ BluetoothAdapter คุณจะค้นหาอุปกรณ์บลูทูธระยะไกลได้ผ่านการค้นหาอุปกรณ์หรือโดยการค้นหารายการอุปกรณ์ที่จับคู่

ตรวจสอบว่าคุณมีสิทธิ์บลูทูธที่เหมาะสมและตั้งค่าแอปสำหรับบลูทูธแล้วก่อนที่จะพยายามค้นหาอุปกรณ์บลูทูธ

การค้นหาอุปกรณ์คือกระบวนการสแกนเพื่อค้นหาอุปกรณ์ที่เปิดใช้บลูทูธในพื้นที่และขอข้อมูลบางอย่างเกี่ยวกับอุปกรณ์แต่ละเครื่อง บางครั้งเราเรียกกระบวนการนี้ว่า "การค้นพบ" "การสอบถาม" หรือ "การสแกน" อุปกรณ์บลูทูธที่อยู่ใกล้เคียงจะตอบกลับคำขอการค้นพบก็ต่อเมื่อกำลังรับคำขอข้อมูลอยู่โดยที่อุปกรณ์สามารถค้นพบได้ หากอุปกรณ์ค้นพบได้ อุปกรณ์จะตอบสนองต่อคำขอการค้นพบด้วยการแชร์ข้อมูลบางอย่าง เช่น ชื่อของอุปกรณ์ คลาสของอุปกรณ์ และที่อยู่ MAC ที่ไม่ซ้ำกัน อุปกรณ์ที่ดำเนินการค้นหาจะเลือกเริ่มการเชื่อมต่อกับอุปกรณ์ที่ค้นพบได้โดยใช้ข้อมูลนี้

เนื่องจากอุปกรณ์ที่ค้นพบได้อาจเปิดเผยข้อมูลเกี่ยวกับตำแหน่งของผู้ใช้ กระบวนการค้นหาอุปกรณ์จึงจำเป็นต้องเข้าถึงตำแหน่ง หากมีการใช้แอปในอุปกรณ์ที่ใช้ Android 8.0 (API ระดับ 26) ขึ้นไป ให้พิจารณาใช้ Companion Device Manager (CDM) API แทน API นี้จะทำการค้นหาอุปกรณ์ในนามของแอป คุณจึงไม่จำเป็นต้องขอสิทธิ์เข้าถึงตำแหน่ง

เมื่อเชื่อมต่อกับอุปกรณ์ระยะไกลเป็นครั้งแรก ระบบจะแสดงคําขอจับคู่ต่อผู้ใช้โดยอัตโนมัติ เมื่อจับคู่อุปกรณ์ ระบบจะบันทึกข้อมูลพื้นฐานเกี่ยวกับอุปกรณ์นั้น เช่น ชื่อ คลาส และที่อยู่ MAC ของอุปกรณ์ และสามารถอ่านข้อมูลดังกล่าวได้โดยใช้ Bluetooth API เมื่อใช้ที่อยู่ MAC ที่ทราบสำหรับอุปกรณ์ระยะไกล คุณจะเริ่มต้นการเชื่อมต่อกับอุปกรณ์ดังกล่าวได้ทุกเมื่อโดยไม่ต้องทำการค้นหา โดยสมมติว่าอุปกรณ์ยังอยู่ในระยะสัญญาณ

โปรดทราบว่าการจับคู่และการเชื่อมต่อนั้นมีความแตกต่างกัน

  • การจับคู่หมายความว่าอุปกรณ์ 2 เครื่องรับรู้ถึงการมีอยู่ของกันและกัน มีคีย์ลิงก์ที่แชร์ซึ่งสามารถใช้ตรวจสอบสิทธิ์ได้ และสามารถสร้างการเชื่อมต่อที่เข้ารหัสระหว่างกันได้
  • เชื่อมต่อหมายความว่าอุปกรณ์ใช้แชแนล RFCOMM ร่วมกันและสามารถส่งข้อมูลถึงกันได้ Bluetooth API ปัจจุบันกำหนดให้ต้องจับคู่อุปกรณ์ก่อนจึงจะสร้างการเชื่อมต่อ RFCOMM ได้ การจับคู่จะดำเนินการโดยอัตโนมัติเมื่อคุณเริ่มการเชื่อมต่อที่เข้ารหัสด้วย Bluetooth API

ส่วนต่อไปนี้จะอธิบายวิธีค้นหาอุปกรณ์ที่จับคู่ไว้และวิธีค้นหาอุปกรณ์ใหม่โดยใช้การค้นหาอุปกรณ์

ค้นหาอุปกรณ์ที่จับคู่แล้ว

ก่อนทำการค้นหาอุปกรณ์ คุณควรค้นหาชุดอุปกรณ์ที่จับคู่ไว้เพื่อดูว่าอุปกรณ์ที่ต้องการรู้จักอยู่แล้วหรือไม่ โดยโทรไปที่ getBondedDevices() ซึ่งจะแสดงชุดออบเจ็กต์ BluetoothDevice ที่แสดงถึงอุปกรณ์ที่จับคู่ ตัวอย่างเช่น คุณสามารถค้นหาอุปกรณ์ที่จับคู่ทั้งหมดและรับชื่อและที่อยู่ MAC ของอุปกรณ์แต่ละเครื่องได้ ดังที่แสดงในตัวอย่างโค้ดต่อไปนี้

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
   }
}

หากต้องการเริ่มการเชื่อมต่อกับอุปกรณ์บลูทูธ สิ่งที่ต้องการจากออบเจ็กต์ BluetoothDevice ที่เชื่อมโยงคือที่อยู่ MAC ซึ่งคุณเรียกดูได้โดยเรียกใช้ getAddress() ดูข้อมูลเพิ่มเติมเกี่ยวกับการสร้างการเชื่อมต่อได้ในเชื่อมต่ออุปกรณ์บลูทูธ

สำรวจอุปกรณ์

หากต้องการเริ่มค้นหาอุปกรณ์ ให้โทรไปที่ startDiscovery() กระบวนการนี้เป็นแบบไม่พร้อมกันและจะแสดงผลค่าบูลีนซึ่งระบุว่าการค้นพบเริ่มต้นสําเร็จหรือไม่ โดยปกติแล้ว กระบวนการค้นหาจะเกี่ยวข้องกับการสแกนสอบถามประมาณ 12 วินาที ตามด้วยการสแกนหน้าเว็บของอุปกรณ์แต่ละเครื่องที่พบเพื่อดึงข้อมูลชื่อบลูทูธ

หากต้องการรับข้อมูลเกี่ยวกับอุปกรณ์แต่ละเครื่องที่ค้นพบ แอปของคุณต้องลงทะเบียน BroadcastReceiver ให้กับ Intent ACTION_FOUND ระบบจะประกาศความตั้งใจนี้สำหรับอุปกรณ์แต่ละเครื่อง Intent มีฟิลด์เพิ่มเติม EXTRA_DEVICE และ EXTRA_CLASS ซึ่งแต่ละฟิลด์มี BluetoothDevice และ BluetoothClass ตามลำดับ ข้อมูลโค้ดต่อไปนี้แสดงวิธีลงทะเบียนเพื่อจัดการการออกอากาศเมื่อตรวจพบอุปกรณ์

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

หากต้องการเริ่มการเชื่อมต่อกับอุปกรณ์บลูทูธ ให้เรียกใช้ getAddress() ใน BluetoothDevice เพื่อดึงข้อมูลที่อยู่ MAC ที่เชื่อมโยง

เปิดใช้การค้นพบได้

หากต้องการให้อุปกรณ์ในเครื่องค้นพบได้ ให้เรียกใช้ startActivityForResult(Intent, int) ด้วย Intent ACTION_REQUEST_DISCOVERABLE ซึ่งจะส่งคําขอเปิดใช้โหมดที่ค้นพบได้ของระบบโดยไม่ต้องไปที่แอปการตั้งค่า ซึ่งจะหยุดแอปของคุณเอง โดยค่าเริ่มต้น อุปกรณ์จะค้นพบได้เป็นเวลา 2 นาที คุณกำหนดระยะเวลาอื่นได้สูงสุด 5 นาทีโดยเพิ่ม EXTRA_DISCOVERABLE_DURATION เพิ่มเติม

ข้อมูลโค้ดต่อไปนี้จะตั้งค่าให้อุปกรณ์ค้นพบได้เป็นเวลา 5 นาที

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


รูปที่ 2: กล่องโต้ตอบการเปิดใช้การค้นพบได้

กล่องโต้ตอบจะปรากฏขึ้นเพื่อขอสิทธิ์จากผู้ใช้ในการทำให้อุปกรณ์ค้นพบได้ ดังที่แสดงในรูปที่ 2 หากผู้ใช้ตอบว่า "อนุญาต" อุปกรณ์จะค้นพบได้เป็นเวลาที่กำหนด จากนั้นกิจกรรมของคุณจะได้รับคําเรียกใช้onActivityResult() callback พร้อมรหัสผลลัพธ์เท่ากับระยะเวลาที่อุปกรณ์ค้นพบได้ หากผู้ใช้ตอบกลับว่า "ปฏิเสธ" หรือหากเกิดข้อผิดพลาดขึ้น รหัสผลลัพธ์จะเป็น RESULT_CANCELED

อุปกรณ์จะอยู่ในโหมดที่ค้นพบได้โดยอัตโนมัติตามเวลาที่กําหนด หากต้องการรับการแจ้งเตือนเมื่อโหมดที่ค้นพบได้เปลี่ยนแปลง ให้ลงทะเบียน BroadcastReceiver สำหรับ Intent ACTION_SCAN_MODE_CHANGED Intent นี้มีช่องเพิ่มเติม EXTRA_SCAN_MODE และ EXTRA_PREVIOUS_SCAN_MODE ซึ่งระบุโหมดการสแกนใหม่และโหมดการสแกนเก่าตามลำดับ ค่าที่เป็นไปได้สำหรับแต่ละextra มีดังนี้

SCAN_MODE_CONNECTABLE_DISCOVERABLE
อุปกรณ์อยู่ในโหมดค้นพบได้
SCAN_MODE_CONNECTABLE
อุปกรณ์ไม่ได้อยู่ในโหมดที่ค้นพบได้ แต่ยังคงรับการเชื่อมต่อได้
SCAN_MODE_NONE
อุปกรณ์ไม่ได้อยู่ในโหมดที่ค้นพบได้และไม่สามารถรับการเชื่อมต่อ

หากเป็นผู้เริ่มการเชื่อมต่อกับอุปกรณ์ระยะไกล คุณไม่จำเป็นต้องเปิดใช้การค้นพบอุปกรณ์ การเปิดใช้การค้นพบจำเป็นเฉพาะในกรณีที่คุณต้องการให้แอปโฮสต์ซ็อกเก็ตเซิร์ฟเวอร์ที่ยอมรับการเชื่อมต่อขาเข้า เนื่องจากอุปกรณ์ระยะไกลต้องสามารถค้นพบอุปกรณ์อื่นๆ ก่อนที่จะเริ่มการเชื่อมต่อกับอุปกรณ์เหล่านั้น