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 tu app se ejecuta en segundo plano:
- Cómo encontrar un dispositivo
- Cómo conectarse a un dispositivo
- Cómo permanecer conectado a un dispositivo
Existen varias opciones para admitir cada uno de estos casos de uso. Cada uno tiene ventajas y desventajas que pueden hacerlo 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, la app debe encontrar un dispositivo al que conectarse. Para encontrar un dispositivo BLE, puedes usar cualquiera de las siguientes APIs:
BluetoothLeScanner
, como se describe en Cómo encontrar dispositivos BLE. (Ejemplo).CompanionDeviceManager
, como se describe en Vinculación de dispositivos complementarios. (Ejemplo).
En segundo plano
No hay limitaciones para usar cualquiera de estas APIs mientras la app no sea visible, pero ambas necesitan que el proceso de la app esté activo. Si el proceso de la app no se está ejecutando, 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 escanee un dispositivo que coincida con tu filtro. (Ejemplo). - Para
CompanionDeviceManager
: Sigue las instrucciones que se indican en Mantén activas las apps complementarias para activar la app y mantenerla activa mientras un dispositivo asociado anteriormente está dentro del alcance. (Ejemplo).
Conectarse a un dispositivo
Para conectarte a un dispositivo después de encontrarlo, debes obtener una instancia de BluetoothDevice
para el dispositivo desde una de las siguientes fuentes:
- Un resultado de análisis de
BluetoothLeScanner
, como se describe en la sección anterior - La lista de dispositivos vinculados recuperada de
BluetoothAdapter.getBondedDevices()
- La caché de
BluetoothAdapter
, que usaBluetoothAdapter.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 directamente al dispositivo periférico y 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 el periférico inicie una desconexión o porque esté fuera de alcance, el cliente GATT intentará reconectarse 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 se cancela el proceso. Además, existen restricciones sobre el inicio de actividades (en Android 10 y versiones posteriores) o servicios en primer plano (en Android 12 y versiones posteriores) desde segundo plano.
Por lo tanto, para realizar una conexión en segundo plano, las apps pueden usar las siguientes soluciones:
- Usa WorkManager para conectarte a tu dispositivo.
- Puedes configurar un
PeriodicWorkRequest
o unOneTimeWorkRequest
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, el trabajo acelerado, la política de reintento y mucho más.
- Si la conexión debe mantenerse activa el mayor tiempo posible para realizar una tarea, como la sincronización de datos o la sondeo desde los dispositivos periféricos, debes iniciar un servicio en primer plano siguiendo las instrucciones que se indican en Compatibilidad con trabajadores de larga duración. Sin embargo, las restricciones para el inicio del servicio en primer plano se aplican a partir de Android 12.
- Puedes configurar un
- 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 la sincronización de datos o la sondeo desde los dispositivos periféricos, debes iniciar un servicio en primer plano siguiendo las instrucciones que se indican en Compatibilidad con trabajadores de larga duración. Sin embargo, las restricciones para el inicio del servicio en primer plano se aplican a partir de Android 12.
- 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 estar transmitiendo anuncios.- Te recomendamos que inicies un trabajador y un trabajo. El sistema puede interrumpir esta comunicación, por lo que solo puede admitir comunicaciones de corta duración.
- En versiones anteriores a Android 12, puedes iniciar un servicio en primer plano directamente desde el objeto
PendingIntent
.
- Usa
CompanionDeviceService
y cualquiera de los permisosREQUEST_COMPANION_RUN_IN_BACKGROUND
oREQUEST_COMPANION_START_FOREGROUND_SERVICES_FROM_BACKGROUND
para iniciar el servicio en segundo plano.
Cómo permanecer conectado a un dispositivo
Lo ideal es que las apps mantengan las conexiones con los dispositivos periféricos solo el tiempo que sea necesario y se desconecten una vez que se complete la tarea. Sin embargo, hay 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()
. - Iniciar un servicio en primer plano mientras la app está en primer plano (o dentro de una de las exenciones) con el tipo de primer plano
connectedDevice
Mientras cambias de app
Encontrar un dispositivo, conectarse a él y transferir datos lleva tiempo y requiere muchos recursos. Para evitar perder la conexión y tener que realizar todo el proceso cada vez que el usuario cambia de app o realiza 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 dispositivos complementarios.
Mientras escuchas notificaciones de periféricos
Para escuchar notificaciones de periféricos, la app debe llamar a setCharacteristicNotification()
, escuchar devoluciones de llamada con onCharacteristicChanged()
y mantener la conexión activa. Para la mayoría de las apps, es mejor admitir este caso de uso con CompanionDeviceService
, ya que es probable que la app deba seguir escuchando durante largos períodos de tiempo. Sin embargo, también puedes usar un servicio en primer plano.
En cualquier caso, puedes volver a conectarte después de un proceso cerrado siguiendo las instrucciones de la sección Cómo conectarse a un dispositivo.