Trovare dispositivi Bluetooth

Con BluetoothAdapter, puoi trovare dispositivi Bluetooth remoti tramite il rilevamento dei dispositivi o tramite una query sull'elenco dei dispositivi accoppiati.

Assicurati di disporre delle autorizzazioni Bluetooth appropriate e di configurare l'app per il Bluetooth prima di tentare di trovare dispositivi Bluetooth.

La ricerca dei dispositivi è una procedura di scansione che cerca dispositivi con Bluetooth abilitato nell'area locale e richiede alcune informazioni su ciascuno. Questo procedura è a volte definita rilevamento, ricerca o scansione. Un dispositivo Bluetooth nelle vicinanze risponde a una richiesta di rilevamento solo se al momento accetta richieste di informazioni essendo rilevabile. Se un dispositivo è rilevabile, risponde alla richiesta di rilevamento condividendo alcune informazioni, come il nome, la classe e l'indirizzo MAC univoco del dispositivo. Utilizzando queste informazioni, il dispositivo che esegue la procedura di rilevamento può scegliere di avviare una connessione con il dispositivo rilevato.

Poiché i dispositivi rilevabili potrebbero rivelare informazioni sulla posizione dell'utente, la procedura di rilevamento dei dispositivi richiede l'accesso alla posizione. Se la tua app viene utilizzata su un dispositivo con Android 8.0 (livello API 26) o versioni successive, ti consigliamo di utilizzare l'API Companion Device Manager. Questa API svolge il rilevamento dei dispositivi per conto della tua app, quindi la tua app non deve richiedere le autorizzazioni di accesso alla posizione.

Una volta stabilita la connessione con un dispositivo remoto per la prima volta, all'utente viene presentata automaticamente una richiesta di accoppiamento. Quando un dispositivo è accoppiato, le informazioni di base su quel dispositivo, ad esempio il nome, la classe e l'indirizzo MAC, vengono salvate e possono essere lette utilizzando le API Bluetooth. Utilizzando l'indirizzo MAC conosciuto di un dispositivo remoto, è possibile avviare una connessione con il dispositivo in qualsiasi momento senza eseguire il rilevamento, supponendo che il dispositivo sia ancora nel raggio d'azione.

Tieni presente che esiste una differenza tra accoppiamento e connessione:

  • L'accoppiamento indica che due dispositivi sono a conoscenza dell'esistenza l'uno dell'altro, hanno una chiave di collegamento condivisa che può essere utilizzata per l'autenticazione e sono in grado di stabilire una connessione criptata tra loro.
  • Per essere connessi, i dispositivi devono attualmente condividere un canale RFCOMM e essere in grado di trasmettere dati tra loro. Le attuali API Bluetooth richiedono l'accoppiamento dei dispositivi prima che possa essere stabilita una connessione RFCOMM. L'accoppiamento viene eseguito automaticamente quando avvii una connessione criptata con le API Bluetooth.

Le sezioni seguenti descrivono come trovare i dispositivi accoppiati e come rilevare nuovi dispositivi utilizzando il rilevamento dei dispositivi.

Eseguire query sui dispositivi accoppiati

Prima di eseguire il rilevamento dei dispositivi, vale la pena eseguire una query sull'insieme di dispositivi accoppiati per verificare se il dispositivo desiderato è già noto. Per farlo, chiama getBondedDevices(). Restituisce un insieme di oggetti BluetoothDevice rappresentanti i dispositivi accoppiati. Ad esempio, puoi eseguire query su tutti i dispositivi accoppiati e recuperare il nome e l'indirizzo MAC di ciascun dispositivo, come dimostra il seguente snippet di codice:

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

Per avviare una connessione con un dispositivo Bluetooth, è sufficiente l'indirizzo MAC dell'oggetto BluetoothDevice associato, che puoi recuperare chiamando getAddress(). Puoi approfondire la creazione di una connessione in Collegare dispositivi Bluetooth.

Scoprire i dispositivi

Per iniziare a rilevare i dispositivi, chiama startDiscovery(). Il processo è asincrono e restituisce un valore booleano che indica se la ricerca è stata avviata correttamente. La procedura di rilevamento prevede in genere una scansione di indagine di circa 12 secondi, seguita da una scansione di pagina di ogni dispositivo trovato per recuperare il nome Bluetooth.

Per ricevere informazioni su ogni dispositivo rilevato, la tua app deve registrare un BroadcastReceiver per l'intent ACTION_FOUND. Il sistema trasmette questo intento per ogni dispositivo. L'intent contiene i campi aggiuntivi EXTRA_DEVICE e EXTRA_CLASS, che a loro volta contengono rispettivamente un BluetoothDevice e un BluetoothClass. Il seguente snippet di codice mostra come registrarsi per gestire la trasmissione quando vengono rilevati i dispositivi:

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

Per avviare una connessione con un dispositivo Bluetooth, chiami getAddress() su BluetoothDevice per recuperare l'indirizzo MAC associato.

Attivare la rilevabilità

Per rendere il dispositivo locale rilevabile da altri dispositivi, chiama startActivityForResult(Intent, int) con l'intent ACTION_REQUEST_DISCOVERABLE. Viene inviata una richiesta per attivare la modalità rilevabile del sistema senza dover accedere all'app Impostazioni, che interrompe la tua app. Per impostazione predefinita, il dispositivo diventa rilevabile per due minuti. Puoi definire una durata diversa, fino a cinque minuti, aggiungendo l'extra EXTRA_DISCOVERABLE_DURATION.

Il seguente snippet di codice imposta il dispositivo in modo che sia rilevabile per cinque minuti:

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


Figura 2: finestra di dialogo per l'attivazione della rilevabilità.

Viene visualizzata una finestra di dialogo che richiede all'utente l'autorizzazione per rendere il dispositivo rilevabile, come mostrato nella figura 2. Se l'utente risponde "Consenti", il dispositivo diventa rilevabile per il periodo di tempo specificato. La tua attività riceve quindi una chiamata al callback onActivityResult(), con il codice risultato uguale alla durata per cui il dispositivo è rilevabile. Se l'utente ha risposto "Rifiuta" o se si è verificato un errore, il codice risultato è RESULT_CANCELED.

Il dispositivo rimane in modalità rilevabile in silenzio per il tempo assegnato. Per ricevere una notifica quando la modalità rilevabile è cambiata, registra un BroadcastReceiver per l'intent ACTION_SCAN_MODE_CHANGED. Questo intento contiene i campi aggiuntivi EXTRA_SCAN_MODE e EXTRA_PREVIOUS_SCAN_MODE, che forniscono rispettivamente la nuova e la vecchia modalità di scansione. I valori possibili per ogni extra sono i seguenti:

SCAN_MODE_CONNECTABLE_DISCOVERABLE
Il dispositivo è in modalità rilevabile.
SCAN_MODE_CONNECTABLE
Il dispositivo non è in modalità rilevabile, ma può comunque ricevere connessioni.
SCAN_MODE_NONE
Il dispositivo non è in modalità rilevabile e non può ricevere connessioni.

Se stai avviando la connessione a un dispositivo remoto, non è necessario attivare la rilevabilità del dispositivo. L'attivazione della rilevabilità è necessaria solo se vuoi che la tua app ospiti un socket del server che accetti connessioni incoming, poiché i dispositivi remoti devono essere in grado di rilevare altri dispositivi prima di avviare le connessioni a questi altri dispositivi.