Este guia apresenta uma visão geral de como oferecer suporte aos principais casos de uso para se comunicar com dispositivos periféricos quando o app está em execução em segundo plano:
Há várias opções para cada um desses casos de uso. Cada um tem vantagens e desvantagens que podem torná-lo mais ou menos adequado para suas necessidades específicas.
O diagrama a seguir mostra uma visualização simplificada das orientações desta página:
Encontrar um dispositivo
Primeiro, o app precisa encontrar um dispositivo para se conectar. Para encontrar um dispositivo BLE, use uma das seguintes APIs:
BluetoothLeScanner
, conforme descrito em Encontrar dispositivos BLE. (Exemplo)CompanionDeviceManager
, conforme descrito em Pareamento de dispositivos complementares. (Exemplo)
Em segundo plano
Não há limitação para usar qualquer uma dessas APIs enquanto o app não está visível, mas ambas precisam que o processo do app esteja ativo. Se o processo do app não estiver em execução, use as seguintes soluções alternativas:
- Para
BluetoothLeScanner
: chamestartScan()
com um objetoPendingIntent
em vez de um objetoScanCallback
para ser notificado quando um dispositivo que corresponde ao filtro for lido. (Exemplo) - Para
CompanionDeviceManager
: siga as orientações em Manter os apps complementares ativados para ativar o app e mantê-lo ativo enquanto um dispositivo associado anteriormente estiver no alcance. (Exemplo)
Conectar a um dispositivo
Para se conectar a um dispositivo depois de encontrá-lo, é necessário receber uma
instância BluetoothDevice
dele
de uma das seguintes fontes:
- Um resultado de verificação
BluetoothLeScanner
, conforme descrito na seção anterior. - A lista de dispositivos pareados recuperada de
BluetoothAdapter.getBondedDevices()
. - O cache
BluetoothAdapter
, usandoBluetoothAdapter.getRemoteLeDevice()
.
Depois de ter uma instância BluetoothDevice
, é possível iniciar uma solicitação de conexão
ao dispositivo correspondente chamando um dos
métodos
connectGatt()
. O valor transmitido para o booleano autoConnect
define qual dos
dois modos de conexão a seguir o cliente GATT usa:
- Conexão direta (
autoconnect = false
): tenta se conectar ao dispositivo periférico diretamente e falha se o dispositivo não estiver disponível. Em caso de desconexão, o cliente GATT não tenta se reconectar automaticamente. - Conexão automática (
autoconnect = true
): tente se conectar automaticamente ao dispositivo periférico sempre que ele estiver disponível. Em caso de desconexão iniciada pelo periférico ou porque ele está fora do alcance, o cliente GATT tenta se reconectar automaticamente quando o periférico está disponível.
Em segundo plano
Não há restrição para se conectar a um dispositivo enquanto o app está em segundo plano, mas a conexão será encerrada se o processo for encerrado. Além disso, há restrições ao início de atividades (no Android 10 e mais recentes) ou de serviços em primeiro plano (no Android 12 e mais recentes) em segundo plano.
Portanto, para realizar uma conexão em segundo plano, os apps podem usar as seguintes soluções:
- Use o WorkManager para se conectar ao
seu dispositivo.
- É possível definir um
PeriodicWorkRequest
ou umOneTimeWorkRequest
para realizar uma ação definida, embora restrições de apps possam ser aplicadas. - Além disso, você pode aproveitar os recursos do WorkManager, como restrições de trabalho, trabalho acelerado, política de nova tentativa e muito mais.
- Se a conexão precisar ser mantida por mais tempo para realizar uma tarefa, como sincronização de dados ou pesquisa de dispositivos periféricos, será necessário iniciar um serviço em primeiro plano seguindo as orientações em Suporte para workers de longa duração. No entanto, as restrições de inicialização de serviços em primeiro plano se aplicam a partir do Android 12.
- É possível definir um
- Inicie um serviço em primeiro plano com o tipo
connectedDevice
.- Se a conexão precisar ser mantida por mais tempo para realizar uma tarefa, como sincronização de dados ou pesquisa de dispositivos periféricos, será necessário iniciar um serviço em primeiro plano seguindo as orientações em Suporte para workers de longa duração. No entanto, as restrições de inicialização de serviços em primeiro plano se aplicam a partir do Android 12.
- Chame
startScan()
com um objetoPendingIntent
, conforme descrito em Encontrar um dispositivo para ativar o processo quando o dispositivo estiver presente. O dispositivo periférico precisa estar anunciando.- Recomendamos que você inicie um worker e um job. Isso pode ser interrompido pelo sistema e, portanto, só pode ser usado para comunicações de curta duração.
- Em versões anteriores ao Android 12, é possível iniciar um serviço em primeiro plano
diretamente do objeto
PendingIntent
.
- Use
CompanionDeviceService
e uma das permissõesREQUEST_COMPANION_RUN_IN_BACKGROUND
ouREQUEST_COMPANION_START_FOREGROUND_SERVICES_FROM_BACKGROUND
para iniciar o serviço em segundo plano.
Manter a conexão com um dispositivo
O ideal é que os apps mantenham as conexões com dispositivos periféricos apenas enquanto necessário e se desconectem quando a tarefa for concluída. No entanto, há dois casos em que um app pode precisar manter uma conexão ativa indefinidamente:
Em ambos os casos, as seguintes opções estão disponíveis:
- Use
CompanionDeviceService
com a permissãoREQUEST_COMPANION_RUN_IN_BACKGROUND
e o métodoCompanionDeviceManager.startObservingDevicePresence()
. - Iniciar um serviço em primeiro plano enquanto
o app está em primeiro plano (ou em uma das
isenções)
com o tipo de
connectedDevice
em primeiro plano.
Ao alternar entre apps
Encontrar um dispositivo, se conectar a ele e transferir dados é demorado e
consome muitos recursos. Para evitar a perda de conexão e a necessidade de realizar o processo
completo sempre que o usuário alterna entre apps ou realiza tarefas
simultâneas, mantenha a conexão ativa até que a operação seja concluída. É
possível usar um serviço em primeiro plano com o tipo connectedDevice
ou a
API de presença de dispositivo
companeiro.
Ao ouvir notificações periféricas
Para ouvir notificações periféricas, o app precisa chamar
setCharacteristicNotification()
,
ouvir callbacks usando
onCharacteristicChanged()
e manter a conexão ativa. Para a maioria dos apps, é melhor oferecer suporte a esse caso de uso
com CompanionDeviceService
, porque o app provavelmente precisará continuar ouvindo
por longos períodos. No entanto, você também pode usar um serviço em primeiro plano.
Em ambos os casos, é possível se reconectar após um processo encerrado seguindo as instruções na seção Conectar a um dispositivo.