البحث عن أجهزة تتضمّن بلوتوث

باستخدام BluetoothAdapter، يمكنك العثور على أجهزة البلوتوث البعيدة إما من خلال ميزة "اكتشاف الأجهزة" أو من خلال البحث في قائمة الأجهزة المقترنة.

تأكَّد من توفّر أذونات البلوتوث المناسبة وإعداد تطبيقك للاتصال بالبلوتوث قبل محاولة العثور على أجهزة البلوتوث.

اكتشاف الأجهزة هو إجراء بحث يبحث في المنطقة المحلية عن devicesالتي تتضمّن بلوتوث ويطلب بعض المعلومات عن كل جهاز. ويُشار إلى هذه العملية أحيانًا باسم "الاكتشاف" أو "الاستعلام" أو "المسح". لا يستجيب جهاز بلوتوث مجاور لطلب اكتشاف إلا إذا كان يقبل حاليًا طلبات المعلومات من خلال جعله قابلاً للاكتشاف. إذا كان الجهاز قابلاً للاكتشاف، يستجيب لطلب الاكتشاف من خلال مشاركة بعض المعلومات، مثل اسم الجهاز وفئة الجهاز وعنوان MAC الفريد. باستخدام هذه المعلومات، يمكن للجهاز الذي يجري عملية الاكتشاف اختيار بدء الاتصال بالجهاز الذي تم اكتشافه.

ولأنّ الأجهزة القابلة للاكتشاف قد تكشف معلومات عن الموقع الجغرافي للمستخدم، تتطلّب عملية اكتشاف الأجهزة الوصول إلى الموقع الجغرافي. إذا كان تطبيقك يتم استخدامه على جهاز يعمل بنظام التشغيل Android 8.0 (المستوى 26 لواجهة برمجة التطبيقات) أو إصدار أحدث، ننصحك باستخدام واجهة برمجة التطبيقات Companion Device Manager بدلاً من ذلك. تُجري واجهة برمجة التطبيقات هذه عملية اكتشاف الأجهزة نيابةً عن تطبيقك، لذا لا يحتاج تطبيقك إلى طلب أذونات تحديد الموقع الجغرافي.

بعد إجراء اتصال بجهاز عن بُعد لأول مرة، يتم تلقائيًا عرض طلب إقران على المستخدم. عند إقران جهاز، يتم حفظ المعلومات الأساسية عن هذا الجهاز، مثل اسم الجهاز وفئة الجهاز وعنوان MAC ، ويمكن قراءتها باستخدام واجهات برمجة تطبيقات البلوتوث. باستخدام عنوان MAC المعروف لجهاز عن بُعد، يمكن بدء الاتصال به في أي وقت بدون إجراء عملية رصد، بافتراض أنّ الجهاز لا يزال ضمن النطاق.

يُرجى العلم أنّ هناك فرقًا بين الاقتران والاتصال:

  • يعني الإقران أنّ الجهازَين على دراية بوجود بعضهما، ويملكان مفتاح ربط مشترَكًا يمكن استخدامه للمصادقة، ويمكنهما إنشاء اتصال مشفَّر مع بعضهما.
  • يشير الاتصال إلى أنّ الأجهزة تشارك حاليًا قناة RFCOMM ويمكنها نقل البيانات مع بعضها. تتطلّب واجهات برمجة التطبيقات الحالية لتقنية البلوتوث إقران الأجهزة قبل أن تتمكّن من بدء اتصال RFCOMM. يتم إجراء الإقران تلقائيًا عند بدء اتصال مشفَّر باستخدام واجهات برمجة التطبيقات Bluetooth.

توضّح الأقسام التالية كيفية العثور على الأجهزة التي تم إقرانها وكيفية اكتشاف الأجهزة الجديدة باستخدام ميزة "اكتشاف الأجهزة".

طلب البحث عن الأجهزة المقترنة

قبل إجراء عملية اكتشاف الأجهزة، من المفيد الاستعلام عن مجموعة الأجهزة المقترنة لمعرفة ما إذا كان الجهاز المطلوب معروفًا. لإجراء ذلك، يُرجى الاتصال بالرقم 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 بهدف ACTION_FOUND. يُرسِل النظام هذا الطلب لكل جهاز. يحتوي الإجراء على الحقول الإضافية 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) باستخدام الإجراء ACTION_REQUEST_DISCOVERABLE. يؤدي ذلك إلى إرسال طلب لتفعيل وضع "الاكتشاف" في النظام بدون الانتقال إلى تطبيق "الإعدادات" الذي سيؤدي إلى إيقاف تطبيقك. وبدلاً من ذلك، يصبح الجهاز قابلاً للاكتشاف لمدة دقيقتين تلقائيًا. يمكنك تحديد مدّة مختلفة تصل إلى خمس دقائق من خلال إضافة الرمز EXTRA_DISCOVERABLE_DURATION الإضافي.

يضبط مقتطف الرمز التالي الجهاز ليكون قابلاً للاكتشاف لمدة خمس دقائق:

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. إذا ردّ المستخدم "السماح"، يصبح الجهاز متاحًا للاكتشاف خلال المدة المحدّدة. بعد ذلك، يتلقّى نشاطك مكالمة إلى دالة callback الخاصة بـ onActivityResult() ، مع رمز النتيجة الذي يساوي المدة التي يكون فيها الجهاز قابلاً للاكتشاف. إذا ردّ المستخدم "رفض" أو إذا حدث خطأ، يكون رمز نتيجة RESULT_CANCELED.

يظل الجهاز في وضع الاكتشاف بدون إشعارك خلال الوقت المحدَّد. لتلقّي إعلام عند تغيير وضع الاكتشاف، سجِّل BroadcastReceiver للغرض ACTION_SCAN_MODE_CHANGED. يحتوي هذا الإجراء على الحقلَين الإضافيَين EXTRA_SCAN_MODE و EXTRA_PREVIOUS_SCAN_MODE، اللذَين يقدّمان وضعَي المسح الضوئي الجديد والقديم، على التوالي. في ما يلي القيم المحتمَلة لكل عمود extra:

SCAN_MODE_CONNECTABLE_DISCOVERABLE
الجهاز في وضع الاكتشاف
SCAN_MODE_CONNECTABLE
الجهاز ليس في وضع الاكتشاف، ولكن لا يزال بإمكانه تلقّي عمليات الربط.
SCAN_MODE_NONE
الجهاز ليس في وضع الاكتشاف ولا يمكنه تلقّي عمليات الربط.

إذا كنت تبدأ عملية الاتصال بجهاز عن بُعد، ليس عليك تفعيل ميزة العثور على الجهاز. لا يكون تفعيل ميزة رصد الأجهزة ضروريًا إلا عندما تريد أن يستضيف تطبيقك مقبس خادم يقبل اتصالات واردة، لأنّ الأجهزة البعيدة يجب أن تتمكّن من رصد الأجهزة الأخرى قبل بدء اتصالات بهذه الأجهزة الأخرى.