En esta guía, se proporciona una descripción general de cómo admitir casos de uso clave para comunicarse con dispositivos periféricos cuando la app se ejecuta en segundo plano:
Hay varias opciones de compatibilidad para cada uno de estos casos de uso. Cada uno tiene ventajas y desventajas que podrían hacer que sea más o menos adecuado para tus necesidades específicas.
En el siguiente diagrama, se muestra una vista simplificada de la guía de esta página:
Buscar un dispositivo
Primero, tu app necesita encontrar un dispositivo al cual conectarse. Para buscar un dispositivo BLE, puedes usar cualquiera de las siguientes APIs:
BluetoothLeScanner
, como se describe en Cómo buscar dispositivos BLE (Muestra)CompanionDeviceManager
, como se describe en Vinculación de dispositivos complementarios. (Muestra)
En segundo plano
No hay límites para usar ninguna de estas APIs cuando la app no está visible, pero ambas necesitan que el proceso de la app esté activo. Si el proceso de la app no se ejecuta, puedes usar las siguientes soluciones alternativas:
- Para
BluetoothLeScanner
: Llama astartScan()
con un objetoPendingIntent
en lugar de un objetoScanCallback
para recibir una notificación cuando se analice un dispositivo que coincide con tu filtro. (Muestra) - Para
CompanionDeviceManager
: Sigue las instrucciones que se indican en Cómo mantener activas las apps complementarias para activarla y mantenerla activa mientras un dispositivo asociado anteriormente esté dentro del rango. (Muestra)
Conectarse a un dispositivo
Si quieres conectarte a un dispositivo después de haberlo encontrado, debes obtener una instancia de BluetoothDevice
para el dispositivo desde una de las siguientes fuentes:
- Un resultado del análisis de
BluetoothLeScanner
como se describe en la sección anterior - La lista de dispositivos vinculados se recuperó de
BluetoothAdapter.getBondedDevices()
. - La caché
BluetoothAdapter
, conBluetoothAdapter.getRemoteLeDevice()
Después de tener una instancia de BluetoothDevice
, puedes iniciar una solicitud de conexión al dispositivo correspondiente llamando a uno de los métodos connectGatt()
. El valor que pasas al booleano autoConnect
define cuál de los siguientes dos modos de conexión usa el cliente GATT:
- Conexión directa (
autoconnect = false
): Intenta conectarte al dispositivo periférico directamente. Falla si el dispositivo no está disponible. En caso de desconexión, el cliente GATT no intenta volver a conectarse automáticamente. - Conexión automática (
autoconnect = true
): Intenta conectarte automáticamente al dispositivo periférico cuando esté disponible. En caso de que se produzca una desconexión por parte del periférico o porque este se encuentra fuera del alcance, el cliente GATT intenta volver a conectarse automáticamente cuando el periférico está disponible.
En segundo plano
No hay restricciones para conectarse a un dispositivo mientras la app está en segundo plano, aunque la conexión se cierra si el proceso se cierra. Además, existen restricciones para iniciar actividades (en Android 10 y versiones posteriores) o servicios en primer plano (en Android 12 y versiones posteriores) en segundo plano.
Por lo tanto, para realizar una conexión mientras se ejecuta en segundo plano, las apps pueden usar las siguientes soluciones:
- Usa WorkManager para conectarte a tu dispositivo.
- Puedes configurar un objeto
PeriodicWorkRequest
oOneTimeWorkRequest
para realizar una acción definida, aunque es posible que se apliquen restricciones de apps. - Además, puedes beneficiarte de las funciones de WorkManager, como las restricciones de trabajo, los trabajos acelerados, la política de reintentos y mucho más.
- Si la conexión debe mantenerse activa el mayor tiempo posible para realizar una tarea, como sincronizar datos o sondear desde los dispositivos periféricos, debes iniciar un servicio en primer plano según las instrucciones en Compatibilidad con trabajadores de larga duración. Sin embargo, a partir de Android 12, se aplican restricciones para el inicio del servicio en primer plano.
- Puedes configurar un objeto
- Inicia un servicio en primer plano con el tipo
connectedDevice
.- Si la conexión debe mantenerse activa el mayor tiempo posible para realizar una tarea, como sincronizar datos o sondear desde los dispositivos periféricos, debes iniciar un servicio en primer plano según las instrucciones en Compatibilidad con trabajadores de larga duración. Sin embargo, a partir de Android 12, se aplican restricciones para el inicio del servicio en primer plano.
- Llama a
startScan()
con un objetoPendingIntent
como se describe en Cómo encontrar un dispositivo para activar el proceso cuando el dispositivo esté presente. El dispositivo periférico debe mostrar publicidad.- Te recomendamos que comiences un objeto Worker y Job. Es posible que el sistema lo interrumpa y, por lo tanto, solo puede admitir una comunicación de corta duración.
- En las versiones anteriores a Android 12, puedes iniciar un servicio en primer plano directamente desde el objeto
PendingIntent
.
- Usa
CompanionDeviceService
y los permisosREQUEST_COMPANION_RUN_IN_BACKGROUND
oREQUEST_COMPANION_START_FOREGROUND_SERVICES_FROM_BACKGROUND
para iniciar el servicio en segundo plano.
Mantente conectado a un dispositivo
Lo ideal sería que las apps mantengan conexiones con dispositivos periféricos solo el tiempo necesario y se desconecten una vez que se complete la tarea. Sin embargo, existen dos casos en los que una app podría necesitar mantener una conexión activa de forma indefinida:
En ambos casos, están disponibles las siguientes opciones:
- Usa
CompanionDeviceService
con el permisoREQUEST_COMPANION_RUN_IN_BACKGROUND
y el métodoCompanionDeviceManager.startObservingDevicePresence()
. - Inicia un servicio en primer plano mientras la app está en primer plano (o dentro de una de las exenciones) con el tipo
connectedDevice
en primer plano.
Al cambiar de app
Encontrar un dispositivo, conectarse a él y transferir datos requiere mucho tiempo y recursos. Para evitar perder la conexión y tener que realizar todo el proceso cada vez que el usuario cambie de app o realice tareas simultáneas, debes mantener la conexión activa hasta que finalice la operación. Puedes usar un servicio en primer plano con el tipo connectedDevice
o la API de presencia de dispositivo complementario.
Mientras se escuchan las notificaciones de periféricos
Para escuchar las notificaciones de periféricos, la app debe llamar a setCharacteristicNotification()
, escuchar las devoluciones de llamada con onCharacteristicChanged()
y mantener activa la conexión. Para la mayoría de las apps, es mejor admitir este caso de uso con CompanionDeviceService
, ya que es probable que la app necesite seguir escuchando durante períodos prolongados. Sin embargo, también puedes usar un servicio en primer plano.
En cualquier caso, puedes volver a conectarte después de que finalizó un proceso siguiendo las instrucciones de la sección Cómo conectarse a un dispositivo.