Encontrar dispositivos Bluetooth

Usando o BluetoothAdapter, é possível encontrar dispositivos Bluetooth remotos pela descoberta de dispositivos ou consultando a lista de dispositivos pareados.

Verifique se você tem as permissões de Bluetooth adequadas e configure seu app para Bluetooth antes de tentar encontrar dispositivos Bluetooth.

A descoberta de dispositivos é um procedimento de busca que procura na área local dispositivos com Bluetooth e solicita algumas informações sobre cada um. Isso processo é chamado às vezes de descoberta, consulta ou varredura. Um dispositivo Bluetooth próximo só responde a uma solicitação de descoberta que aceita solicitações de informações por ser detectável. Se um dispositivo for detectável, ele responde à solicitação de descoberta compartilhando algumas informações, como o nome do dispositivo, sua classe e seu endereço MAC único. Usar este do aplicativo, o dispositivo que executa o processo de descoberta pode escolher para iniciar uma conexão com o dispositivo descoberto.

Como os dispositivos detectáveis podem revelar informações sobre a localização do usuário, o processo de descoberta de dispositivos exige acesso à localização. Se o app estiver sendo usado em um dispositivo com o Android 8.0 (nível 26 da API) ou versões mais recentes, use o Gerenciador de dispositivos complementar API. Esta API realiza a descoberta de dispositivos em nome do app, de modo que ele não precise solicitar permissões de localização.

Depois de estabelecer uma conexão com um dispositivo remoto pela primeira vez, um procedimento é apresentada automaticamente ao usuário. Quando um dispositivo é pareado, o informações básicas sobre o dispositivo, como nome, classe e MAC é salvo e pode ser lido usando as APIs de Bluetooth. Como usar o MAC conhecido para um dispositivo remoto, é possível iniciar uma conexão com ele a qualquer momento sem realizar a descoberta, supondo que o dispositivo ainda esteja dentro do alcance.

Lembre-se de que há uma diferença entre estar pareado e estar conectado:

  • pareado significa que dois dispositivos estão cientes da existência um do outro, uma chave de link compartilhada que pode ser usada para autenticação e capaz de estabelecendo uma conexão criptografada entre si.
  • Estar conectado significa que os dispositivos compartilham atualmente um canal RFCOMM e são capazes de transmitir dados entre si. O Bluetooth atual As APIs exigem que os dispositivos estejam pareados antes de uma conexão RFCOMM ser estabelecidos. O pareamento é feito automaticamente quando você inicia um com as APIs de Bluetooth.

As seções a seguir descrevem como encontrar os dispositivos que já foram pareados e como descobrir novos dispositivos usando a descoberta de dispositivos.

Consultar dispositivos pareados

Antes de realizar a descoberta de dispositivos, vale a pena consultar o conjunto de para ver se o dispositivo desejado já é conhecido. Para fazer isso, chame o método getBondedDevices(). Isso retorna um conjunto de Objetos BluetoothDevice que representam dispositivos pareados. Por exemplo, você pode consultar todos os dispositivos pareados e para saber o nome e o endereço MAC de cada dispositivo, conforme o snippet de código a seguir. demonstra:

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

Para iniciar uma conexão com um dispositivo Bluetooth, basta acessar o objeto BluetoothDevice associado é o endereço MAC, que você recupera pelo chamar getAddress(). Você pode saber mais sobre como criar uma conexão em Conectar Bluetooth dispositivos.

Descobrir dispositivos

Para começar a descobrir dispositivos, chame startDiscovery() O processo é assíncrono e retorna um valor booleano que indica se a descoberta foi iniciada. O processo de descoberta geralmente envolve de aproximadamente 12 segundos, seguida por uma verificação de página de cada dispositivo encontrado para recuperar o nome do Bluetooth.

Para receber informações sobre cada dispositivo descoberto, seu app precisa registrar um BroadcastReceiver para o ACTION_FOUND intenção. O sistema transmite esse intent para cada dispositivo. A intent contém os campos extras EXTRA_DEVICE e EXTRA_CLASS, que por sua vez, contêm um BluetoothDevice e um BluetoothClass, respectivamente. O snippet de código a seguir mostra como se registrar para processar a transmissão quando dispositivos são descobertos:

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

Para iniciar uma conexão com um dispositivo Bluetooth, chame getAddress() no BluetoothDevice para recuperar o endereço MAC associado.

Ativar a detecção do dispositivo

Para tornar o dispositivo local detectável para outros dispositivos, chame startActivityForResult(Intent, int) com o ACTION_REQUEST_DISCOVERABLE intenção. Isso emite uma solicitação para ativar o modo detectável do sistema sem ter que navegar até o app Configurações, o que interromperia seu próprio app. De padrão, o dispositivo se torna detectável por dois minutos. Você pode definir duração diferente, de até uma hora, adicionando o EXTRA_DISCOVERABLE_DURATION extra.

O snippet de código a seguir define o dispositivo como detectável por cinco minutos:

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


de Figura 2. Caixa de diálogo de ativação da detecção do dispositivo.

Uma caixa de diálogo é exibida, solicitando a permissão do usuário para tornar o dispositivo detectável, como mostrado na Figura 2. Se o usuário responder "Permitir", então o o dispositivo se torna detectável pelo tempo especificado. Sua atividade então recebe uma chamada onActivityResult() com o código de resultado igual à duração em que o dispositivo detectáveis. Se o usuário respondeu "Negar" ou se ocorreu um erro, o resultado o código é RESULT_CANCELED.

O dispositivo permanecerá silenciosamente no modo detectável pelo tempo especificado. Para ser notificado quando o modo detectável mudar, registre um BroadcastReceiver para o ACTION_SCAN_MODE_CHANGED intenção. Essa intent contém os campos extras EXTRA_SCAN_MODE e EXTRA_PREVIOUS_SCAN_MODE, que fornecem o modo de busca novo e antigo, respectivamente. Os valores possíveis para cada são os seguintes:

SCAN_MODE_CONNECTABLE_DISCOVERABLE
O dispositivo está no modo detectável.
SCAN_MODE_CONNECTABLE
O dispositivo não está no modo detectável, mas ainda pode receber conexões.
SCAN_MODE_NONE
O dispositivo não está no modo detectável e não pode receber conexões.

Se você estiver iniciando a conexão a um dispositivo remoto, não será necessário ativar a detecção do dispositivo. A ativação da detecção do dispositivo só é necessária você quer que seu app hospede um soquete de servidor que aceite conexões de rede, já que os dispositivos remotos precisam ser capazes de descobrir outros dispositivos antes iniciando conexões com esses outros dispositivos.