Este guia fornece uma visão geral de como oferecer suporte aos principais casos de uso de comunicação com dispositivos periféricos quando o app estiver sendo executado em segundo plano:
Há várias opções para cada um desses casos de uso. Cada uma tem vantagens e desvantagens que podem torná-las mais ou menos adequadas para suas necessidades específicas.
O diagrama a seguir mostra uma visualização simplificada das orientações nesta página:
Encontre um dispositivo
Primeiro, seu app precisa encontrar um dispositivo para se conectar. Para encontrar um dispositivo BLE, use uma destas APIs:
BluetoothLeScanner
, conforme descrito em Encontrar dispositivos BLE. (Exemplo)CompanionDeviceManager
, conforme descrito em Pareamento de dispositivo complementar. (Exemplo)
Em segundo plano
Não há limitação para o uso de 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 estas soluções alternativas:
- Para
BluetoothLeScanner
: chamestartScan()
com um objetoPendingIntent
em vez de um objetoScanCallback
para receber uma notificação quando um dispositivo correspondente ao filtro for verificado. (Exemplo) - Para
CompanionDeviceManager
: siga as orientações em Manter os apps complementares ativados para ativar o app e mantê-lo ativado enquanto um dispositivo anteriormente associado estiver dentro do alcance. (Exemplo)
Conectar a um dispositivo
Para se conectar a um dispositivo depois de encontrá-lo, você precisa acessar uma instância
BluetoothDevice
para
ele usando uma destas fontes:
- Um resultado de verificação
BluetoothLeScanner
, conforme descrito na seção anterior. - A lista de dispositivos vinculados recuperada de
BluetoothAdapter.getBondedDevices()
. - O cache
BluetoothAdapter
, usandoBluetoothAdapter.getRemoteLeDevice()
.
Quando você tiver uma instância de BluetoothDevice
, será possível iniciar uma solicitação de conexão
com o 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 diretamente ao dispositivo periférico e falha se o dispositivo não estiver disponível. Em caso de desconexão, o cliente GATT não tentará se reconectar automaticamente. - Conexão automática (
autoconnect = true
): tente se conectar automaticamente ao dispositivo periférico sempre que ele estiver disponível. No caso de uma desconexão iniciada pelo periférico ou porque o periférico está fora do alcance, o cliente GATT tentará se reconectar automaticamente quando o periférico estiver disponível.
Em segundo plano
Não há restrições para se conectar a um dispositivo enquanto o app está em segundo plano, embora a conexão seja encerrada se o processo for encerrado. Além disso, há restrições para iniciar atividades (no Android 10 e versões mais recentes) ou serviços em primeiro plano (no Android 12 e versões mais recentes) em segundo plano.
Assim, para executar uma conexão em segundo plano, os apps podem usar as seguintes soluções:
- Use o WorkManager para se conectar ao
dispositivo.
- É possível definir uma
PeriodicWorkRequest
ou umaOneTimeWorkRequest
para realizar uma ação definida, embora restrições de app possam ser aplicadas. - Além disso, você pode se beneficiar dos recursos do WorkManager, como restrições de trabalho, trabalho priorizado, política de novas tentativas e muito mais.
- Se a conexão precisar ser mantida ativa o maior tempo possível para executar uma tarefa, como sincronização de dados ou pesquisa de dispositivos periféricos, você precisará iniciar um serviço em primeiro plano seguindo as orientações em Suporte para workers de longa execução. No entanto, restrições de inicialização de serviços em primeiro plano se aplicam a partir do Android 12.
- É possível definir uma
- Inicie um serviço em primeiro plano com o tipo
connectedDevice
.- Se a conexão precisar ser mantida ativa o maior tempo possível para executar uma tarefa, como sincronização de dados ou pesquisa de dispositivos periféricos, você precisará iniciar um serviço em primeiro plano seguindo as orientações em Suporte para workers de longa execução. No entanto, 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 ser publicitário.- Recomendamos que você inicie um worker e um job. Ela pode ser interrompida pelo sistema e, portanto, só permite comunicações de curta duração.
- Em versões anteriores ao Android 12, é possível iniciar um serviço em primeiro plano
diretamente no 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 conexões com dispositivos periféricos somente pelo tempo 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()
. - Inicie um serviço
em primeiro plano enquanto
o app estiver em primeiro plano (ou dentro de uma das
isenções)
com o
tipo
connectedDevice
em primeiro plano.
Ao alternar entre apps
Encontrar um dispositivo, conectar-se a ele e transferir dados leva tempo e
exige muitos recursos. Para evitar a perda de conexão e a necessidade de realizar o processo completo
sempre que o usuário alternar entre apps ou realizar tarefas simultâneas, mantenha a conexão ativa até que a operação seja concluída. Você
pode usar um serviço em primeiro plano com o tipo connectedDevice
ou a
API de presença de dispositivo
complementar.
Ao ouvir notificações de periféricos
Para detectar notificações de periféricos, o app precisa chamar
setCharacteristicNotification()
,
detectar 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 detectando
por longos períodos. No entanto, também é possível 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.