Com o BluetoothAdapter
,
é possível encontrar dispositivos remotos Bluetooth 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 usar o Bluetooth antes de tentar encontrar dispositivos Bluetooth.
A descoberta de dispositivos é um procedimento de verificação que procura dispositivos com Bluetooth na área local e solicita algumas informações sobre cada um deles. Esse processo às vezes é chamado de descoberta, consulta ou verificação. Um dispositivo Bluetooth próximo responde a uma solicitação de descoberta somente se estiver aceitando solicitações de informações sendo detectável. Se um dispositivo for detectável, ele vai responder à solicitação de descoberta compartilhando algumas informações, como o nome, a classe e o endereço MAC exclusivo do dispositivo. Com essas informações, o dispositivo que está executando o processo de descoberta pode optar por iniciar uma conexão com o dispositivo descoberto.
Como dispositivos detectáveis podem revelar informações sobre a localização do usuário, o processo de descoberta de dispositivos requer acesso à localização. Caso seu app esteja sendo usado em um dispositivo com o Android 8.0 (nível 26 da API) ou versões mais recentes, considere usar a API Companion Device Manager. Essa API realiza a descoberta de dispositivos em nome do seu app. Assim, ele não precisa solicitar permissões de localização.
Depois que uma conexão com um dispositivo remoto é feita pela primeira vez, uma solicitação de pareamento é apresentada automaticamente ao usuário. Quando um dispositivo é pareado, as informações básicas dele, como nome, classe e endereço MAC, são salvas e podem ser lidas usando as APIs Bluetooth. Com o endereço MAC conhecido de um dispositivo remoto, é possível iniciar uma conexão com ele a qualquer momento sem executar a descoberta, desde que o dispositivo ainda esteja dentro do alcance.
Lembre-se de que há uma diferença entre estar pareado e estar conectado:
- Estar pareado significa que os dois dispositivos estão cientes da existência um do outro, têm uma chave de link compartilhada que pode ser usada para autenticação e podem estabelecer uma conexão criptografada entre si.
- Estar conectado significa que os dispositivos compartilham um canal RFCOMM e são capazes de transmitir dados entre si. As APIs Bluetooth atuais exigem que os dispositivos estejam pareados antes de estabelecer uma conexão RFCOMM. O pareamento é realizado automaticamente quando você inicia uma conexão criptografada com as APIs Bluetooth.
As seções a seguir descrevem como encontrar dispositivos que 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 dispositivos
pareados para ver se o dispositivo desejado já é conhecido. Para fazer isso,
chame o método getBondedDevices()
.
Isso retorna um conjunto de objetos
BluetoothDevice
que representa dispositivos pareados. Por exemplo, é possível consultar todos os dispositivos pareados e
conseguir o nome e o endereço MAC de cada dispositivo, conforme demonstra o snippet de
código a seguir:
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, tudo o que é necessário do
objeto BluetoothDevice
associado é o endereço MAC, que você extrai
chamando
getAddress()
. Saiba
mais sobre como criar uma conexão em Conectar dispositivos
Bluetooth.
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 com êxito. O processo de descoberta geralmente envolve uma
verificação de cerca de 12 segundos, seguida por uma verificação de páginas de cada dispositivo encontrado
para recuperar o nome Bluetooth.
Para receber informações sobre cada dispositivo descoberto, seu app precisa registrar um
BroadcastReceiver
para a
intent
ACTION_FOUND
. 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 a
intent
ACTION_REQUEST_DISCOVERABLE
. Isso emite uma solicitação para ativar o modo detectável do sistema sem
precisar navegar até o app Configurações, o que interromperia seu próprio app. Por
padrão, o dispositivo fica detectável por dois minutos. Adicione o extra
EXTRA_DISCOVERABLE_DURATION
para definir uma
duração diferente, de até uma hora.
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);
Figura 2:caixa de diálogo de ativação da detecção do dispositivo.
Uma caixa de diálogo vai aparecer solicitando a permissão do usuário para tornar o dispositivo
detectável, conforme mostrado na Figura 2. Se o usuário responder "Permitir", o
dispositivo vai se tornar detectável pelo período especificado. Em seguida, a atividade
recebe uma chamada para o callback
onActivityResult()
,
com o código de resultado igual à duração em que o dispositivo fica
detectável. Se o usuário tiver respondido "Negar" ou se ocorrer um erro, o código do
resultado será RESULT_CANCELED
.
O dispositivo permanecerá silenciosamente no modo detectável pelo tempo especificado. Para receber
uma notificação quando o modo detectável mudar, registre um BroadcastReceiver
para a
intent
ACTION_SCAN_MODE_CHANGED
. Essa intent contém os campos extras EXTRA_SCAN_MODE
e EXTRA_PREVIOUS_SCAN_MODE
, que fornecem o modo de verificação novo e o antigo, respectivamente. Os valores possíveis para cada
extra são estes:
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 com um dispositivo remoto, não precisará ativar a detecção do dispositivo. Isso só é necessário quando você quer que o app hospede um soquete de servidor que aceite conexões de entrada, já que os dispositivos remotos precisam ser capazes de descobrir outros dispositivos antes de iniciar conexões com eles.