Límites de ejecución en segundo plano

Cada vez que una app se ejecuta en segundo plano, consume alguno de los recursos limitados del dispositivo, como la memoria RAM. Esto puede afectar la experiencia del usuario, en especial si este usa una app que requiere de una gran cantidad de recursos, como un juego o un reproductor de video. Para mejorar la experiencia del usuario, Android 8.0 impone limitaciones en las capacidades de las apps mientras se ejecutan en segundo plano. En este documento se describen los cambios en el sistema operativo y el modo en que puedes actualizar tu aplicación para que funcione bien con las limitaciones nuevas.

Información general

Muchas app y servicios de Android se pueden ejecutar de manera simultánea. Por ejemplo, un usuario puede usar un juego en una ventana mientras navega en la web en otra , y recurrir a una tercera app para reproducir música. Cuantas más apps se ejecuten a la vez, mayor será la carga para el sistema. Si se ejecutan más apps o servicios en segundo plano, aumenta la carga del sistema, lo cual puede generar una mala experiencia de usuario; por ejemplo, la app de música se puede cerrar de repente.

Para disminuir las posibilidades de tener estos problemas, Android 8.0 establece limitaciones sobre lo que pueden hacer las apps mientras los usuarios no interactúan directamente con ellas. Existen dos clases de restricciones para las apps:

  • Limitaciones de servicios en segundo plano: Mientras una app está inhabilitada, existen límites para su uso de servicios en segundo plano. Esto no se aplica a servicios en primer plano, que son más notorios para el usuario.

  • Limitaciones de transmisión: A excepción de unos casos limitados, las apps no pueden usar sus manifiestos para registrarse en transmisiones implícitas. Sin embargo, pueden registrarse para estas transmisiones en el tiempo de ejecución y usar los manifiestos a fin de registrarse para transmisiones explícitas destinadas específicamente a ellas.

Nota: De forma predeterminada, estas restricciones se aplican únicamente a apps orientadas a Android 8.0. Sin embargo, los usuarios pueden habilitar estas restricciones para cualquier app desde la pantalla Settings, aunque la app no se haya diseñado para O.

En la mayoría de los casos, las apps pueden lidiar con estas limitaciones usando tareas JobScheduler. Este enfoque permite que un arreglo de apps realice tareas cuando no se está ejecutando activamente; sin embargo, le da al sistema la libertad de programar esas tareas de una forma que no afecte la experiencia del usuario. Android 8.0 ofrece varias mejoras a JobScheduler que facilitan el reemplazo de receptores de transmisión y servicios por tareas programadas; para obtener más información, consulta Mejoras de JobScheduler.

Limitaciones de servicios en segundo plano

Los servicios que se ejecutan en segundo plano pueden consumir recursos del dispositivo, lo que puede empeorar la experiencia del usuario. Para mitigar este problema, el sistema aplica varias limitaciones a los servicios.

El sistema distingue entre apps foreground y background. (La definición de segundo plano para las limitaciones de servicio es diferente de la definición que usa la administración de memoria; una aplicación puede estar en segundo plano cuando corresponde a la administración de memoria y en primer plano cuando corresponde a su capacidad para el lanzamiento de servicios). Se considera que una aplicación se encuentra en primer plano si alguna de las siguientes consideraciones es verdadera:

  • Tiene una actividad visible, independientemente de que la actividad esté iniciada o pausada.
  • Tiene un servicio en primer plano.
  • Otra app en primer plano está conectada con la app, ya sea mediante un enlace con uno de sus servicios o el uso de uno de sus proveedores de contenido. Por ejemplo, la aplicación se encuentra en primer plano si otra se enlaza a su:
    • IME;
    • servicio de fondo de pantalla;
    • receptor de notificación;
    • servicio de voz o texto.

Si ninguna de esas condiciones es true, se considera que la app se encuentra en segundo plano.

Mientras una app se encuentra en primer plano, puede crear y ejecutar servicios en primer y segundo plano libremente. Cuando una app pasa a funcionar en segundo plano, tiene una ventana de varios minutos durante los cuales puede, de todos modos, crear y usar servicios. Al final de esa ventana, la app se considera idle. En este momento, el sistema detiene los servicios en segundo plano de la app, como si esta hubiese llamado a los métodos Service.stopSelf() de los servicios.

En determinadas circunstancias, una app en segundo plano se ubica en una lista blanca temporal durante varios minutos. Mientras se encuentre en la lista blanca, una aplicación podrá lanzar servicios sin limitaciones y se permitirá la ejecución de los que estén en segundo plano. Una app se ubica en la lista blanca cuando administra una tarea que es visible para el usuario. Por ejemplo:

En muchos casos, tu app puede reemplazar servicios en segundo plano por tareas JobScheduler. Por ejemplo, CoolPhotoApp debe verificar si el usuario ha recibido fotos compartidas de amigos, incluso si la app no se ejecuta en primer plano. Anteriormente, la app usaba un servicio en segundo plano que se activaba con el almacenamiento en la nube de la app. Para realizar la migración a Android 8.0, el desarrollador reemplaza el servicio de segundo plano por una tarea programada, que se lanza periódicamente, realiza consultas al servidor y luego finaliza.

Antes de Android 8.0, el modo usual de crear un servicio en primer plano consistía en crear un servicio en segundo plano y luego hacer que pasara a funcionar en primer plano. Con Android 8.0, existe una complicación; el sistema no permite que una app que está en segundo plano cree un servicio en segundo plano. Por esta razón, en Android 8.0 se presenta el nuevo método Context.startForegroundService() para iniciar un servicio nuevo en primer plano. Una vez que el sistema crea el servicio, la app tiene cinco segundos para llamar al método startForeground() de dicho servicio a fin de mostrar la notificación visible para el usuario del nuevo servicio. Si la app no llama a startForeground() en ese plazo, el sistema detiene el servicio y declara un estado ANR para esta.

Limitaciones de transmisión

Si una app se registra para recibir transmisiones, el receptor de esta consume recursos cada vez que se realiza una transmisión. Esto puede causar problemas si demasiadas apps se registran para recibir transmisiones según los eventos del sistema; un evento del sistema que activa una transmisión puede hacer que todas las apps consuman recursos de manera rápida y sucesiva, lo cual puede afectar la experiencia del usuario. Para mitigar este problema, Android 7.0 (nivel de API 25) impuso limitaciones sobre transmisiones, como se describe en Optimización en segundo plano. Android 8.0 hace que estas limitaciones sean más estrictas.

En muchos casos, las apps que se registraron previamente para una transmisión implícita pueden obtener una funcionalidad similar usando una tarea {@link android.app.job.JobScheduler. Por ejemplo, es posible que una app de fotografía social deba realizar una limpieza en sus datos de vez en cuando y priorice hacerlo cuando el dispositivo está conectado a un cargador. Anteriormente, la app registraba un receptor para ACTION_POWER_CONNECTED en su manifiesto; cuando la app recibía esa transmisión, comprobaba si la limpieza era necesaria. Para realizar la migración a Android 8.0, la app quita el receptor de su manifiesto. En cambio, la app programa una tarea de limpieza que se ejecuta cuando el dispositivo está inactivo y se está cargando.

Nota: Varias transmisiones implícitas actualmente quedan exentas de esta limitación. Las apps pueden continuar registrando receptores para estas transmisiones en sus manifiestos, sin importar el nivel de API al cual se orienten. Para acceder a una lista de las transmisiones excluidas, consulta Excepciones de transmisiones implícitas.

Guía de migración

De forma predeterminada, estos cambios solo tienen efecto en apps orientadas a Android 8.0. Sin embargo, los usuarios pueden habilitar estas restricciones para cualquier app desde la pantalla Settings, aunque la app no se haya diseñado para O. Es posible que debas actualizar tu app para que cumpla con las limitaciones nuevas.

Comprueba el modo en que tu app usa los servicios. Si tu app usa servicios que se ejecutan en segundo plano mientras tu app se encuentra inactiva, deberás reemplazarlos. Dentro de las posibles soluciones se incluyen las siguientes:

  • Si tu app debe crear un servicio en primer plano mientras funciona en segundo plano, usa el método nuevo NotificationManager.startServiceInForeground() en lugar de crear un servicio en segundo plano e intentar hacer que pase a funcionar en primer plano.
  • Si el servicio es visible para el usuario, conviértelo en un servicio en segundo plano. Por ejemplo, un servicio que reproduce audio debe ser siempre de primer plano. Crea el servicio con NotificationManager.startServiceInForeground() en lugar de startService().
  • Encuentra una manera de duplicar la funcionalidad del servicio con una tarea programada. Si el servicio no hace algo que sea notorio de manera inmediata para el usuario, por lo general, puedes usar una tarea programada.
  • Usa FCM para activar tu aplicación de manera selectiva cuando se produzcan eventos de red en lugar de realizar sondeos en segundo plano.
  • Difiere tareas en segundo plano hasta que la aplicación se encuentre naturalmente en primer plano.

Revisa los receptores de transmisiones definidos en el manifiesto de tu app. Si tu manifiesto establece a un receptor para una transmisión implícita, debes reemplazarlo. Dentro de las posibles soluciones se incluyen las siguientes:

  • crear el receptor en el tiempo de ejecución llamando a Context.registerReceiver() en lugar de declarar el receptor en el manifiesto;
  • usar una tarea programada para buscar la condición que haya activado la transmisión implícita.