חיפוש מכשירי Bluetooth

באמצעות BluetoothAdapter, ניתן לאתר מכשירי Bluetooth מרוחקים באמצעות גילוי המכשיר או כשמריצים שאילתות על רשימת המכשירים המותאמים.

מוודאים שיש לכם את ההרשאות המתאימות ל-Bluetooth. ולהגדיר את האפליקציה ל-Bluetooth לפני ניסיון לאתר מכשירי Bluetooth.

גילוי מכשיר הוא הליך סריקה המחפש באזור המקומי של מכשירים שמופעל בהם Bluetooth ומבקשים מידע מסוים על כל אחד מהם. הזה מכונה לפעמים גילוי, בירור או סריקה. מכשיר Bluetooth בקרבת מקום מגיב לבקשת גילוי רק אם מקבל בקשות מידע כרגע באמצעות גילוי נאות. אם מכשיר גלוי, הוא מגיב לבקשת הגילוי על ידי שיתוף מידע מסוים, למשל שם המכשיר, הסיווג שלו וכתובת ה-MAC הייחודית. שימוש בטיוטה הזו המכשיר שמבצע את תהליך הגילוי יכול לבחור כדי להתחיל חיבור למכשיר שהתגלה.

מכיוון שמכשירים ניתנים לגילוי עשויים לחשוף מידע על מיקום המשתמש, לתהליך גילוי המכשיר נדרשת גישה למיקום. אם האפליקציה נמצאת בשימוש במכשיר עם Android מגרסה 8.0 (API ברמה 26) ומעלה, כדאי להשתמש ניהול המכשירים הנלווים API במקום זאת. ה-API הזה מבצע גילוי מכשיר בשם האפליקציה, כך שהאפליקציה לא צריכה לבקש הרשאות מיקום.

לאחר יצירת חיבור בפעם הראשונה עם מכשיר מרוחק, מתבצעת התאמה הבקשה מוצגת באופן אוטומטי למשתמש. כשמבצעים התאמה של מכשיר, מידע בסיסי על המכשיר הזה - כגון שם המכשיר, הרמה וה-MAC הכתובת — נשמרת וניתן לקרוא אותה באמצעות ממשקי ה-API של Bluetooth. שימוש ב-MAC הידוע כתובת למכשיר מרוחק, ניתן להתחיל חיבור איתו בכל שלב מבלי לבצע גילוי, בהנחה שהמכשיר עדיין נמצא בטווח.

שימו לב שיש הבדל בין התאמה לבין חיבור:

  • המשמעות של התאמה היא ששני מכשירים מודעים לקיום אחד של השני, יש מפתח קישור משותף שניתן להשתמש בו לאימות וגם ליצור חיבור מוצפן אחד עם השני.
  • המשמעות של התחברות היא שהמכשירים חולקים כרגע ערוץ RFCOMM וגם יכולים לשדר נתונים זה עם זה. חיבור ה-Bluetooth הנוכחי ממשקי API מחייבים התאמה של מכשירים כדי שניתן יהיה להשתמש בחיבור RFCOMM נוצרה. ההתאמה מתבצעת באופן אוטומטי כשמתחילים חיבור לממשקי ה-API של 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
   }
}

כדי להפעיל חיבור עם מכשיר Bluetooth, כל מה שנחוץ לך אובייקט BluetoothDevice המשויך הוא כתובת ה-MAC, שאותה מאחזרים שיחות getAddress(). שלך אפשר לקרוא מידע נוסף על יצירת חיבור בקטע חיבור Bluetooth מכשירים.

Discover מכשירים

כדי להתחיל לגלות מכשירים, צריך להתקשר startDiscovery() התהליך הוא אסינכרוני ומחזיר ערך בוליאני שמציין אם תהליך הגילוי התחיל בהצלחה. בדרך כלל תהליך הגילוי כולל סריקת חקירה של כ-12 שניות, ולאחר מכן סריקת דף של כל מכשיר שנמצא כדי לאחזר את שם ה-Bluetooth שלו.

כדי לקבל מידע על כל מכשיר שמתגלה, האפליקציה שלך צריכה לרשום 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);
}

כדי להתחיל חיבור עם מכשיר Bluetooth, צריך להתקשר למספר 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. אם המשתמש מגיב 'אפשר', אז המכשיר הופך לגלוי למשך הזמן שצוין. הפעילות שלך ואז מקבל קריאה onActivityResult() קריאה חוזרת (callback), כשקוד התוצאה זהה למשך הזמן שהמכשיר שגלוי לכולם. אם המשתמש השיב 'דחייה' או אם אירעה שגיאה, התוצאה הוא RESULT_CANCELED.

המכשיר יישאר במצב גלוי באופן שקט למשך הזמן שהוקצב. להיות קיבלת הודעה כשמצב הגילוי הנאות השתנה, יש לרשום BroadcastReceiver עבור ACTION_SCAN_MODE_CHANGED בכוונה טובה. Intent זה מכיל את השדות הנוספים EXTRA_SCAN_MODE וגם EXTRA_PREVIOUS_SCAN_MODE, שמספקים את מצב הסריקה החדש והישן, בהתאמה. ערכים אפשריים לכל אחד מהם הם:

SCAN_MODE_CONNECTABLE_DISCOVERABLE
המכשיר במצב גלוי.
SCAN_MODE_CONNECTABLE
המכשיר לא במצב גלוי אבל עדיין יכול לקבל חיבורים.
SCAN_MODE_NONE
המכשיר לא במצב גלוי ולא יכול לקבל חיבורים.

אם התחלת את החיבור למכשיר מרוחק, אין צורך לאפשר את יכולת הגילוי של המכשיר. יש להפעיל את יכולת הגילוי רק כאשר שרוצים שהאפליקציה תארח שקע שרת שמקבל חיבורים, כי מכשירים מרוחקים חייבים להיות מסוגלים לגלות מכשירים אחרים לפני התחלת חיבורים למכשירים האחרים האלה.