Las apps orientadas a Android 12 ya no pueden iniciar servicios en primer plano mientras se ejecutan en segundo plano, excepto en algunos casos especiales. Si una app intenta iniciar un servicio en primer plano mientras se ejecuta en segundo plano y el servicio en primer plano no cumple con uno de los casos excepcionales, el sistema arroja una ForegroundServiceStartNotAllowedException
.
Alternativa recomendada a los servicios en primer plano: WorkManager
Si este cambio afecta a la app, comienza a usar WorkManager. WorkManager es la solución que se recomienda para iniciar tareas en segundo plano con mayor prioridad.
A partir de WorkManager 2.7.0, la app puede llamar a setExpedited()
para declarar que Worker
debe usar un trabajo acelerado. Esta nueva API usa trabajos acelerados cuando se ejecuta en Android 12, y la API usa servicios en primer plano en versiones anteriores de Android a fin de brindar retrocompatibilidad.
En el siguiente fragmento de código, se muestra un ejemplo de cómo usar el método setExpedited()
:
Kotlin
OneTimeWorkRequestBuilder<T>().apply { setInputData(inputData) setExpedited(OutOfQuotaPolicy.RUN_AS_NON_EXPEDITED_WORK_REQUEST) }.build()
Java
OneTimeWorkRequest request = new OneTimeWorkRequestBuilder<T>() .setInputData(inputData) .setExpedited(OutOfQuotaPolicy.RUN_AS_NON_EXPEDITED_WORK_REQUEST) .build();
Como los métodos CoroutineWorker.setForeground()
y ListenableWorker.setForegroundAsync()
están respaldados por servicios en primer plano, están sujetos a las mismas restricciones para el inicio del servicio en primer plano y exenciones. Puedes aprovechar la API al máximo, pero prepárate para controlar una excepción si el sistema no permite que la app inicie un servicio en primer plano. Si deseas ofrecer una experiencia más coherente, usa setExpedited()
.
Para ver un ejemplo completo de cómo WorkManager 2.7.0 usa trabajos acelerados, consulta WorkManagerSample en GitHub.
Trabajos acelerados
Los trabajos acelerados, que son nuevos en Android 12, permiten que las apps ejecuten tareas importantes y breves al mismo tiempo que le otorgan al sistema un mejor control sobre el acceso a los recursos.
Estos trabajos tienen un conjunto de características en algún lugar entre un servicio en primer plano y un trabajo normal de JobScheduler
:
- Están diseñados para tareas breves que se completan en pocos minutos. A menos que la app tenga una cuota suficiente, es posible que el sistema detenga un trabajo acelerado si ya se ejecutó por al menos 3 minutos.
- Se ven menos afectados por algunas de las restricciones para la administración de batería del sistema, como el Ahorro de batería y Descanso.
- El sistema las ejecuta de inmediato, siempre que la carga de trabajo actual del sistema permita hacerlo.
Los trabajos acelerados pueden postergarse
El sistema intenta ejecutar un trabajo acelerado determinado lo antes posible una vez que se invoca. Sin embargo, como sucede con otros tipos de trabajos, el sistema podría diferir el inicio de nuevos trabajos acelerados, por ejemplo, en los siguientes casos:
- La carga del sistema es demasiado alta, lo que puede suceder cuando ya se están ejecutando demasiados trabajos o cuando el sistema no cuenta con suficiente memoria.
- Se superó el límite de cuota para trabajos acelerados. Los trabajos acelerados usan un sistema de cuotas basado en los buckets de App Standby y limitan el tiempo máximo de ejecución en un período de tiempo progresivo. Las cuotas que se usan para trabajos acelerados son más restrictivas que las que se usan para otros tipos de trabajos en segundo plano.
Efectos en las API de Alarm Manager
En general, las apps que se orientan a Android 12 no pueden iniciar servicios en primer plano con una alarma.
Para admitir casos de uso en los que las apps necesitan enviarles alarmas o recordatorios urgentes a los usuarios, todavía puedes iniciar servicios en primer plano cuando suenan las alarmas exactas. A fin de configurar este tipo de alarmas, la app debe declarar el permiso SCHEDULE_EXACT_ALARM
.
Obtén más información sobre el permiso de alarmas exactas.
Casos en los que se permite el inicio de servicios en primer plano desde el segundo plano
En las siguientes situaciones, tu app puede iniciar servicios en primer plano incluso mientras se ejecuta en segundo plano:
- La app viene de un estado visible para el usuario, como una actividad.
- La app puede iniciar una actividad en segundo plano, excepto en los casos en que tiene una actividad en la pila de actividades de una tarea existente.
- Tu app recibe un mensaje de prioridad alta mediante Firebase Cloud Messaging.
- El usuario realiza una acción en un elemento de la IU relacionado con tu app. Por ejemplo, puede interactuar con un cuadro de ayuda, una notificación, un widget o una actividad.
- Tu app recibe un evento relacionado con el geovallado o la transición del reconocimiento de actividad.
- Después de que el dispositivo se reinicia y recibe la acción de intent
ACTION_BOOT_COMPLETED
,ACTION_LOCKED_BOOT_COMPLETED
oACTION_MY_PACKAGE_REPLACED
en un receptor de emisión. - La app recibe la acción de intent
ACTION_TIMEZONE_CHANGED
,ACTION_TIME_CHANGED
oACTION_LOCALE_CHANGED
en un receptor de emisión. - La app recibe una emisión de Bluetooth que requiere los permisos
BLUETOOTH_CONNECT
oBLUETOOTH_SCAN
. - Apps que tienen permisos o funciones del sistema específicos, como propietarios del dispositivo y propietarios de perfiles.
Tu app usa el administrador de dispositivo complementario.
Para permitir que el sistema active la app cada vez que se acerque un dispositivo complementario, implementa el servicio de dispositivos complementarios en Android 12.
El sistema reinicia un servicio "fijo" en primer plano. Para lograr que un servicio en primer plano sea fijo, muestra
START_STICKY
oSTART_REDELIVER_INTENT
desdeonStartCommand()
.El usuario desactiva las optimizaciones de la batería para la app. Puedes ayudar a que los usuarios encuentren esta opción si los envías a la página de información de la app en la configuración del sistema. Para ello, invoca un intent que contenga la acción de intent
ACTION_IGNORE_BATTERY_OPTIMIZATION_SETTINGS
.