Bluetooth-Geräte suchen

Mit dem BluetoothAdapter können Sie Remote-Bluetooth-Geräte entweder über die Geräteerkennung oder durch Abfrage der Liste der gekoppelten Geräte finden.

Prüfen Sie, ob Sie die entsprechenden Bluetooth-Berechtigungen haben und richten Sie Ihre App für Bluetooth ein, bevor Sie nach Bluetooth-Geräten suchen.

Die Geräteerkennung ist ein Scanvorgang, bei dem in der lokalen Umgebung nach Bluetooth-fähigen Geräten gesucht wird. Zu jedem dieser Geräte werden Informationen angefordert. Dieser Vorgang wird manchmal als Erkennen, Anfrage oder Scannen bezeichnet. Ein Bluetooth-Gerät in der Nähe reagiert nur dann auf eine Anfrage zur Erkennung, wenn es derzeit Informationsanfragen akzeptiert, indem es sichtbar ist. Wenn ein Gerät sichtbar ist, antwortet es auf die Erkennungsanfrage mit einigen Informationen, z. B. dem Namen des Geräts, seiner Klasse und seiner eindeutigen MAC-Adresse. Anhand dieser Informationen kann das Gerät, das den Erkennungsprozess durchführt, dann eine Verbindung zum erkannten Gerät initiieren.

Da sichtbare Geräte Informationen zum Standort des Nutzers preisgeben können, benötigt die Geräteerkennung Zugriff auf den Standort. Wenn Ihre App auf einem Gerät mit Android 8.0 (API-Level 26) oder höher ausgeführt wird, sollten Sie stattdessen die Companion Device Manager API verwenden. Diese API führt die Geräteerkennung im Namen Ihrer App durch, sodass Ihre App keine Berechtigungen zur Standortermittlung anfordern muss.

Sobald zum ersten Mal eine Verbindung zu einem Remote-Gerät hergestellt wurde, wird dem Nutzer automatisch eine Kopplungsanfrage angezeigt. Wenn ein Gerät gekoppelt ist, werden die grundlegenden Informationen zu diesem Gerät – z. B. Name, Klasse und MAC-Adresse – gespeichert und können mit den Bluetooth APIs gelesen werden. Mithilfe der bekannten MAC-Adresse für ein Remote-Gerät kann jederzeit eine Verbindung dazu hergestellt werden, ohne dass eine Erkennung durchgeführt werden muss. Dabei wird vorausgesetzt, dass sich das Gerät noch in Reichweite befindet.

Beachte, dass es einen Unterschied zwischen der Kopplung und der Verbindung gibt:

  • Gekoppelt bedeutet, dass zwei Geräte sich gegenseitig erkennen, einen gemeinsamen Linkschlüssel haben, der für die Authentifizierung verwendet werden kann, und eine verschlüsselte Verbindung zueinander herstellen können.
  • Verbunden bedeutet, dass die Geräte derzeit einen RFCOMM-Kanal nutzen und Daten untereinander übertragen können. Für die aktuellen Bluetooth APIs müssen die Geräte gekoppelt sein, bevor eine RFCOMM-Verbindung hergestellt werden kann. Die Kopplung wird automatisch durchgeführt, wenn Sie eine verschlüsselte Verbindung mit den Bluetooth APIs herstellen.

In den folgenden Abschnitten wird beschrieben, wie du gekoppelte Geräte und mithilfe der Geräteerkennung findest.

Gekoppelte Geräte abfragen

Vor der Geräteerkennung empfiehlt es sich, die gekoppelten Geräte abzufragen, um festzustellen, ob das gewünschte Gerät bereits bekannt ist. Rufen Sie dazu getBondedDevices() auf. Dadurch wird eine Reihe von BluetoothDevice-Objekten zurückgegeben, die gekoppelte Geräte darstellen. Sie können beispielsweise alle gekoppelten Geräte abfragen und den Namen und die MAC-Adresse jedes Geräts abrufen, wie das folgende Code-Snippet zeigt:

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

Zum Initiieren einer Verbindung mit einem Bluetooth-Gerät benötigt das zugehörige BluetoothDevice-Objekt nur die MAC-Adresse, die Sie durch Aufrufen von getAddress() abrufen. Weitere Informationen zum Herstellen einer Verbindung finden Sie unter Bluetooth-Geräte verbinden.

Geräte entdecken

Rufen Sie startDiscovery() auf, um mit der Geräteerkennung zu beginnen. Der Prozess ist asynchron und gibt einen booleschen Wert zurück, der angibt, ob die Erkennung erfolgreich gestartet wurde. Der Erkennungsprozess umfasst in der Regel einen etwa zwölf Sekunden dauernden Anfragescan, gefolgt von einem Seitenscan jedes gefundenen Geräts, um seinen Bluetooth-Namen abzurufen.

Damit Sie Informationen zu jedem erkannten Gerät erhalten können, muss Ihre App einen BroadcastReceiver für den ACTION_FOUND-Intent registrieren. Das System überträgt diesen Intent für jedes Gerät. Der Intent enthält die zusätzlichen Felder EXTRA_DEVICE und EXTRA_CLASS, die wiederum ein BluetoothDevice- bzw. BluetoothClass-Feld enthalten. Das folgende Code-Snippet zeigt, wie Sie sich für die Verarbeitung der Übertragung registrieren können, wenn Geräte erkannt werden:

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

Wenn Sie eine Verbindung mit einem Bluetooth-Gerät herstellen möchten, rufen Sie getAddress() im BluetoothDevice auf, um die zugehörige MAC-Adresse abzurufen.

Sichtbarkeit aktivieren

Damit das lokale Gerät für andere Geräte sichtbar ist, rufen Sie startActivityForResult(Intent, int) mit dem ACTION_REQUEST_DISCOVERABLE-Intent auf. Dadurch wird eine Anfrage zum Aktivieren des Erkennungsmodus des Systems ausgegeben, ohne die App „Einstellungen“ aufrufen zu müssen, wodurch Ihre eigene App beendet wird. Standardmäßig ist das Gerät zwei Minuten lang sichtbar. Sie können eine andere Dauer von maximal einer Stunde definieren, indem Sie das zusätzliche EXTRA_DISCOVERABLE_DURATION-Element hinzufügen.

Mit dem folgenden Code-Snippet ist das Gerät fünf Minuten lang sichtbar:

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


Abbildung 2:Dialogfeld zum Aktivieren der Auffindbarkeit.

Es wird ein Dialogfeld angezeigt, in dem der Nutzer um seine Erlaubnis gebeten wird, das Gerät sichtbar zu machen (siehe Abbildung 2). Wenn der Nutzer mit „Zulassen“ antwortet, ist das Gerät für den angegebenen Zeitraum sichtbar. Bei Ihrer Aktivität wird dann ein Aufruf an den onActivityResult()-Callback empfangen. Der Ergebniscode entspricht der Dauer, während der das Gerät sichtbar ist. Wenn der Nutzer mit „Ablehnen“ geantwortet hat oder ein Fehler aufgetreten ist, lautet der Ergebniscode RESULT_CANCELED.

Das Gerät bleibt während der vorgegebenen Zeit im Erkennungsmodus. Wenn Sie benachrichtigt werden möchten, wenn sich der Erkennungsmodus geändert hat, registrieren Sie einen BroadcastReceiver für den Intent ACTION_SCAN_MODE_CHANGED. Dieser Intent enthält die zusätzlichen Felder EXTRA_SCAN_MODE und EXTRA_PREVIOUS_SCAN_MODE, die den neuen bzw. den alten Scanmodus bereitstellen. Mögliche Werte für jedes Extra sind:

SCAN_MODE_CONNECTABLE_DISCOVERABLE
Das Gerät befindet sich im Modus „Sichtbar“.
SCAN_MODE_CONNECTABLE
Das Gerät befindet sich nicht im Modus „Sichtbar“, kann aber Verbindungen annehmen.
SCAN_MODE_NONE
Das Gerät befindet sich nicht im Modus „Sichtbar“ und kann keine Verbindungen herstellen.

Wenn Sie die Verbindung zu einem Remote-Gerät herstellen, müssen Sie die Gerätesichtbarkeit nicht aktivieren. Das Aktivieren der Sichtbarkeit ist nur dann erforderlich, wenn Ihre Anwendung einen Server-Socket hosten soll, der eingehende Verbindungen akzeptiert, da Remote-Geräte andere Geräte erkennen müssen, bevor sie Verbindungen zu diesen Geräten initiieren.