Rechercher des appareils Bluetooth

À l'aide de BluetoothAdapter, vous pouvez trouver des appareils Bluetooth distants via la détection d'appareils ou en interrogeant la liste des appareils associés.

Assurez-vous de disposer des autorisations Bluetooth appropriées et configurez votre application pour le Bluetooth avant d'essayer de trouver des appareils Bluetooth.

La détection d'appareils est une procédure de recherche qui recherche des appareils compatibles Bluetooth dans la zone locale et demande des informations sur chacun d'eux. Ce processus est parfois appelé "découverte", "demande d'informations" ou "analyse". Un appareil Bluetooth à proximité ne répond à une requête de découverte que s'il accepte actuellement des requêtes d'informations en étant visible. Si un appareil est visible, il répond à la requête de découverte en partageant certaines informations, telles que son nom, sa classe et son adresse MAC unique. À l'aide de ces informations, l'appareil qui effectue le processus de découverte peut alors choisir d'établir une connexion à l'appareil détecté.

Étant donné que les appareils visibles peuvent révéler des informations sur la position de l'utilisateur, le processus de détection des appareils nécessite un accès à la position. Si votre application est utilisée sur un appareil exécutant Android 8.0 (niveau d'API 26) ou une version ultérieure, envisagez plutôt d'utiliser l'API Companion Device Manager. Cette API effectue la détection d'appareils pour le compte de votre application. Votre application n'a donc pas besoin de demander l'autorisation d'accéder à la position.

Lorsqu'une connexion est établie avec un appareil distant pour la première fois, une demande d'association est automatiquement présentée à l'utilisateur. Lorsqu'un appareil est associé, les informations de base le concernant, telles que son nom, sa classe et son adresse MAC, sont enregistrées et peuvent être lues à l'aide des API Bluetooth. En utilisant l'adresse MAC connue d'un appareil distant, une connexion peut être établie avec celui-ci à tout moment sans effectuer de découverte, à condition que l'appareil soit toujours à portée.

Notez qu'il existe une différence entre être associé et connecté:

  • Pour être associés, deux appareils sont conscients de l'existence de l'autre, disposent d'une clé de lien partagée pouvant être utilisée pour l'authentification et sont capables d'établir une connexion chiffrée l'un avec l'autre.
  • Pour être connectés, les appareils partagent actuellement un canal RFCOMM et peuvent transmettre des données entre eux. Les API Bluetooth actuelles nécessitent que les appareils soient associés avant qu'une connexion RFCOMM puisse être établie. L'association est effectuée automatiquement lorsque vous démarrez une connexion chiffrée avec les API Bluetooth.

Les sections suivantes décrivent comment rechercher des appareils associés et comment découvrir de nouveaux appareils à l'aide de la détection d'appareils.

Interroger les appareils associés

Avant d'effectuer la détection d'appareils, il est utile d'interroger l'ensemble d'appareils associés pour voir si l'appareil souhaité est déjà connu. Pour ce faire, appelez getBondedDevices(). Cette commande renvoie un ensemble d'objets BluetoothDevice représentant des appareils associés. Par exemple, vous pouvez interroger tous les appareils associés et obtenir le nom et l'adresse MAC de chaque appareil, comme le montre l'extrait de code suivant:

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

Pour établir une connexion avec un appareil Bluetooth, l'objet BluetoothDevice associé n'a besoin que de l'adresse MAC, que vous récupérez en appelant getAddress(). Pour en savoir plus sur la création d'une connexion, consultez Connecter des appareils Bluetooth.

Découvrir des appareils

Pour commencer à détecter les appareils, appelez startDiscovery(). Le processus est asynchrone et renvoie une valeur booléenne indiquant si la découverte a bien démarré. Le processus de découverte implique généralement une analyse de requête d'environ 12 secondes, suivie d'une analyse de page de chaque appareil détecté pour récupérer son nom Bluetooth.

Pour recevoir des informations sur chaque appareil détecté, votre application doit enregistrer un BroadcastReceiver pour l'intent ACTION_FOUND. Le système diffuse cet intent pour chaque appareil. L'intent contient les champs supplémentaires EXTRA_DEVICE et EXTRA_CLASS, qui à leur tour contiennent respectivement BluetoothDevice et BluetoothClass. L'extrait de code suivant montre comment vous inscrire pour gérer la diffusion lorsque des appareils sont détectés:

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

Pour établir une connexion avec un appareil Bluetooth, appelez getAddress() sur BluetoothDevice afin de récupérer l'adresse MAC associée.

Activer la visibilité

Pour rendre l'appareil local visible par d'autres appareils, appelez startActivityForResult(Intent, int) avec l'intent ACTION_REQUEST_DISCOVERABLE. Cela envoie une requête pour activer le mode détectable du système sans avoir à accéder à l'application Paramètres, ce qui arrête votre propre application. Par défaut, l'appareil devient visible pendant deux minutes. Vous pouvez définir une durée différente, jusqu'à une heure, en ajoutant l'extra EXTRA_DISCOVERABLE_DURATION.

L'extrait de code suivant définit l'appareil comme visible pendant cinq minutes:

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


Figure 2:Boîte de dialogue d'activation de la visibilité

Une boîte de dialogue s'affiche, demandant l'autorisation de l'utilisateur pour rendre l'appareil visible, comme illustré dans la figure 2. Si l'utilisateur répond "Autoriser", l'appareil devient visible pendant la période spécifiée. Votre activité reçoit ensuite un appel au rappel onActivityResult(), avec un code de résultat égal à la durée pendant laquelle l'appareil est visible. Si l'utilisateur a répondu "Refuser" ou si une erreur s'est produite, le code de résultat est RESULT_CANCELED.

L'appareil reste en mode silencieux pendant le temps imparti. Pour être averti lorsque le mode visible a changé, enregistrez un BroadcastReceiver pour l'intent ACTION_SCAN_MODE_CHANGED. Cet intent contient les champs supplémentaires EXTRA_SCAN_MODE et EXTRA_PREVIOUS_SCAN_MODE, qui fournissent respectivement le nouveau et l'ancien mode d'analyse. Les valeurs possibles pour chaque extra sont les suivantes:

SCAN_MODE_CONNECTABLE_DISCOVERABLE
L'appareil est en mode détectable.
SCAN_MODE_CONNECTABLE
L'appareil n'est pas en mode détectable, mais il peut tout de même recevoir des connexions.
SCAN_MODE_NONE
L'appareil n'est pas en mode détectable et ne peut pas recevoir de connexions.

Si vous démarrez la connexion à un appareil distant, vous n'avez pas besoin d'activer la visibilité de l'appareil. L'activation de la visibilité n'est nécessaire que si vous souhaitez que votre application héberge un socket de serveur qui accepte les connexions entrantes, car les appareils distants doivent pouvoir détecter d'autres appareils avant d'établir des connexions à ces autres appareils.