دستگاه های بلوتوث را پیدا کنید

با استفاده از BluetoothAdapter ، می‌توانید دستگاه‌های بلوتوث راه دور را از طریق کشف دستگاه یا با جستجو در فهرست دستگاه‌های جفت شده پیدا کنید.

مطمئن شوید که مجوزهای بلوتوث مناسب را دارید و قبل از تلاش برای یافتن دستگاه‌های بلوتوث ، برنامه خود را برای بلوتوث تنظیم کنید .

کشف دستگاه یک روش اسکن است که منطقه محلی را برای دستگاه‌های دارای بلوتوث جستجو می‌کند و اطلاعاتی در مورد هر کدام درخواست می‌کند. این فرآیند گاهی اوقات به عنوان کشف، پرس و جو یا اسکن نامیده می شود. یک دستگاه بلوتوث نزدیک تنها در صورتی به درخواست کشف پاسخ می‌دهد که در حال حاضر درخواست‌های اطلاعاتی را با قابلیت شناسایی بپذیرد. اگر دستگاهی قابل کشف باشد، با به اشتراک گذاشتن برخی اطلاعات، مانند نام دستگاه، کلاس آن و آدرس MAC منحصر به فرد آن، به درخواست کشف پاسخ می دهد. با استفاده از این اطلاعات، دستگاهی که فرآیند کشف را انجام می‌دهد، می‌تواند انتخاب کند که اتصال به دستگاه کشف شده را آغاز کند.

از آنجایی که دستگاه‌های قابل کشف ممکن است اطلاعاتی را درباره مکان کاربر نشان دهند، فرآیند کشف دستگاه نیاز به دسترسی به مکان دارد. اگر برنامه شما در دستگاهی استفاده می‌شود که دارای Android 8.0 (سطح API 26) یا بالاتر است، به جای آن از Companion Device Manager API استفاده کنید. این API از طرف برنامه شما کشف دستگاه را انجام می دهد، بنابراین برنامه شما نیازی به درخواست مجوزهای مکان ندارد.

هنگامی که برای اولین بار با یک دستگاه راه دور ارتباط برقرار می شود، درخواست جفت شدن به طور خودکار به کاربر ارائه می شود. هنگامی که یک دستگاه جفت می شود، اطلاعات اولیه مربوط به آن دستگاه - مانند نام، کلاس و آدرس MAC دستگاه - ذخیره می شود و با استفاده از API های بلوتوث قابل خواندن است. با استفاده از آدرس MAC شناخته شده برای یک دستگاه راه دور، با فرض اینکه دستگاه هنوز در محدوده قرار دارد، می توان در هر زمان بدون انجام اکتشاف، اتصال با آن را آغاز کرد.

توجه داشته باشید که بین جفت شدن و متصل بودن تفاوت وجود دارد:

  • جفت شدن به این معنی است که دو دستگاه از وجود یکدیگر آگاه هستند، یک کلید پیوند مشترک دارند که می تواند برای احراز هویت استفاده شود، و می توانند یک ارتباط رمزگذاری شده با یکدیگر برقرار کنند.
  • اتصال به این معنی است که دستگاه ها در حال حاضر یک کانال RFCOMM را به اشتراک می گذارند و قادر به انتقال داده ها با یکدیگر هستند. APIهای بلوتوث کنونی به جفت شدن دستگاهها قبل از برقراری اتصال RFCOMM نیاز دارند. هنگامی که یک اتصال رمزگذاری شده با APIهای بلوتوث را شروع می کنید، جفت شدن به طور خودکار انجام می شود.

بخش‌های زیر نحوه یافتن دستگاه‌هایی را که جفت شده‌اند و نحوه کشف دستگاه‌های جدید با استفاده از کشف دستگاه را شرح می‌دهد.

دستگاه های جفت شده را پرس و جو کنید

قبل از انجام کشف دستگاه، ارزش آن را دارد که مجموعه دستگاه های جفت شده را جستجو کنید تا ببینید آیا دستگاه مورد نظر از قبل شناخته شده است یا خیر. برای انجام این کار، getBondedDevices() را فراخوانی کنید. این مجموعه ای از اشیاء BluetoothDevice را نشان می دهد که دستگاه های جفت شده را نشان می دهد. به عنوان مثال، همانطور که قطعه کد زیر نشان می دهد، می توانید تمام دستگاه های جفت شده را پرس و جو کنید و نام و آدرس MAC هر دستگاه را دریافت کنید:

کاتلین

val pairedDevices: Set<BluetoothDevice>? = bluetoothAdapter?.bondedDevices
pairedDevices?.forEach { device ->
   val deviceName = device.name
   val deviceHardwareAddress = device.address // MAC address
}

جاوا

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 برای هدف ACTION_FOUND ثبت کند. سیستم این هدف را برای هر دستگاه پخش می کند. Intent شامل فیلدهای اضافی EXTRA_DEVICE و EXTRA_CLASS است که به نوبه خود شامل یک BluetoothDevice و یک BluetoothClass هستند. قطعه کد زیر نشان می دهد که چگونه می توانید برای مدیریت پخش در هنگام کشف دستگاه ها ثبت نام کنید:

کاتلین

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

جاوا

@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) را با هدف ACTION_REQUEST_DISCOVERABLE فراخوانی کنید. این درخواست برای فعال کردن حالت قابل شناسایی سیستم بدون نیاز به پیمایش به برنامه تنظیمات صادر می کند، که برنامه شما را متوقف می کند. به طور پیش فرض، دستگاه به مدت دو دقیقه قابل شناسایی می شود. با افزودن EXTRA_DISCOVERABLE_DURATION اضافی، می‌توانید مدت زمان متفاوتی، حداکثر یک ساعت، تعریف کنید.

قطعه کد زیر دستگاه را به مدت پنج دقیقه قابل کشف تنظیم می کند:

کاتلین

val requestCode = 1;
val discoverableIntent: Intent = Intent(BluetoothAdapter.ACTION_REQUEST_DISCOVERABLE).apply {
   putExtra(BluetoothAdapter.EXTRA_DISCOVERABLE_DURATION, 300)
}
startActivityForResult(discoverableIntent, requestCode)

جاوا

int requestCode = 1;
Intent discoverableIntent =
       new Intent(BluetoothAdapter.ACTION_REQUEST_DISCOVERABLE);
discoverableIntent.putExtra(BluetoothAdapter.EXTRA_DISCOVERABLE_DURATION, 300);
startActivityForResult(discoverableIntent, requestCode);


شکل 2: گفتگوی قابلیت شناسایی فعال.

گفتگویی نمایش داده می‌شود که از کاربر درخواست می‌کند تا دستگاه را قابل شناسایی کند، همانطور که در شکل 2 نشان داده شده است. اگر کاربر به "اجازه دادن" پاسخ دهد، دستگاه برای مدت زمان مشخص قابل شناسایی می‌شود. سپس اکتیویتی شما یک فراخوانی به پاسخ onActivityResult() دریافت می کند که کد نتیجه آن برابر با مدت زمانی است که دستگاه قابل کشف است. اگر کاربر به "رد کردن" پاسخ داد، یا اگر خطایی رخ داد، کد نتیجه RESULT_CANCELED است.

دستگاه برای مدت زمان تعیین شده بی صدا در حالت قابل شناسایی باقی می ماند. برای اطلاع از تغییر حالت قابل کشف، یک BroadcastReceiver برای هدف ACTION_SCAN_MODE_CHANGED ثبت کنید. این هدف حاوی فیلدهای اضافی EXTRA_SCAN_MODE و EXTRA_PREVIOUS_SCAN_MODE است که به ترتیب حالت اسکن جدید و قدیمی را ارائه می‌کنند. مقادیر ممکن برای هر اضافی به شرح زیر است:

SCAN_MODE_CONNECTABLE_DISCOVERABLE
دستگاه در حالت شناسایی است.
SCAN_MODE_CONNECTABLE
دستگاه در حالت قابل شناسایی نیست اما همچنان می‌تواند اتصالات را دریافت کند.
SCAN_MODE_NONE
دستگاه در حالت قابل شناسایی نیست و نمی تواند اتصالات را دریافت کند.

اگر اتصال به یک دستگاه راه دور را آغاز می کنید، نیازی به فعال کردن قابلیت شناسایی دستگاه ندارید. فعال کردن قابلیت شناسایی تنها زمانی ضروری است که می‌خواهید برنامه شما میزبان یک سوکت سرور باشد که اتصالات ورودی را می‌پذیرد، زیرا دستگاه‌های راه دور باید قبل از شروع اتصال به آن دستگاه‌های دیگر، بتوانند دستگاه‌های دیگر را کشف کنند.