Hibernación de apps

Si la app se orienta a Android 11 (nivel de API 30) o versiones posteriores, y el usuario no interactúa con ella durante unos meses, el sistema la ubica en un estado de hibernación. El sistema optimiza el espacio de almacenamiento en lugar del rendimiento y protege los datos del usuario. Este comportamiento es similar a lo que sucede cuando el usuario fuerza manualmente la detención de la app desde la configuración del sistema.

Efectos de la hibernación

Como se muestra en la tabla 1, los efectos de la hibernación dependen de la versión del SDK de destino de tu app y del dispositivo en el que esta se ejecuta:

Tabla 1: Efectos de la hibernación en tu app
Versión del SDK de destino Características del dispositivo Efectos de la hibernación
Android 12 o versiones posteriores Ejecuta Android 12 o una versión posterior

Se restablecen los permisos de tiempo de ejecución de tu app. Esta acción tiene el mismo efecto que si el usuario viera un permiso en la configuración del sistema y cambiara el nivel de acceso de tu app a Rechazar.

La app no puede ejecutar trabajos ni alertas en segundo plano.

La app no puede recibir notificaciones push, incluidos los mensajes de prioridad alta que se envían a través de Firebase Cloud Messaging.

Se quitan todos los archivos de la caché de la app.

Android 11 Ejecuta Android 11 Se restablecen los permisos de tiempo de ejecución de tu app.
Android 11 Ejecuta desde Android 6.0 (nivel de API 23) hasta Android 10 (nivel de API 29), inclusive, y cuenta con la tecnología de los Servicios de Google Play

Se restablecen los permisos de tiempo de ejecución de tu app.

Este comportamiento entrará en vigencia en diciembre de 2021. Más información en esta entrada de blog sobre cómo hacer que los permisos de restablecimiento automático estén disponibles para miles de millones de dispositivos más.

Comportamiento del sistema cuando una app sale de la hibernación

Cuando el usuario interactúa con la app, esta sale de la hibernación y puede volver a crear trabajos, alertas y notificaciones.

Sin embargo, hay cosas que el sistema no hará para tu app:

  1. No vuelve a otorgar los permisos de tiempo de ejecución de tu app.

    El usuario debe volver a otorgar estos permisos para la app.

  2. No reprograma los trabajos, las alertas y las notificaciones que se programaron antes de que la app entrara en hibernación.

    Para admitir este flujo de trabajo con más facilidad, usa WorkManager. También puedes agregar la lógica de reprogramación en el receptor de emisión ACTION_BOOT_COMPLETED, que se invoca cuando la app sale de la hibernación y después de que se inicia el dispositivo.

Uso de apps

En las siguientes secciones, se proporcionan ejemplos de acciones que se consideran usos de una app y ejemplos de acciones que el sistema no reconoce de la misma manera.

Ejemplos de uso de la app

Cuando se reanuda una actividad en tu app, el sistema considera que este evento es una interacción del usuario. Por lo tanto, el sistema extiende la cantidad de tiempo antes de que la app entre en hibernación.

En Android 11 y versiones posteriores, también se consideran los siguientes comportamientos como interacciones del usuario:

  • El usuario interactúa con un widget.
  • El usuario interactúa con una notificación, excepto cuando descarta la notificación.

Se debe tener en cuenta que el uso de la app para la hibernación no requiere la interacción del usuario de forma explícita. Siempre que se invoque un componente del paquete, se lo considerará un uso de la app. Por ejemplo:

  • Apps que tienen un servicio o proveedor de contenido vinculado por otra app en el dispositivo o SO (por ejemplo, los editores de métodos de entrada, o IME, o los administradores de contraseñas)
  • Los receptores de emisión del paquete que reciben una transmisión explícita de un paquete externo

Ejemplos que no se consideran un uso de la app

Si tu app solo muestra los comportamientos descritos en la siguiente lista, entrará en hibernación al cabo de algunos meses:

Exenciones del sistema al estado de hibernación

En ciertos casos de uso, Android otorga exenciones de hibernación de apps a nivel de sistema. Si tu app se encuentra en una de las siguientes categorías, está exenta de los estándares de uso de apps y no entrará en hibernación.

Apps que no se muestran en el selector
Se trata de cualquier app que no tenga una tarjeta activa de accesos directos en el selector.
Apps del perfil de trabajo
Se trata de cualquier app que un usuario instale en un perfil de trabajo. Ten en cuenta que, si la misma app también reside en un perfil personal, solo estará exenta la app del perfil de trabajo.
Controladores de políticas de dispositivo
Se trata de las apps que controlan las políticas de dispositivos locales y las aplicaciones del sistema en los dispositivos.
Apps con privilegios de operador
Cualquier app que los operadores de telefonía celular carguen previamente en los dispositivos y consideren necesarias para las obligaciones contractuales del servicio, por ejemplo, las apps de buzón de voz o de atención al cliente.
Apps de instalación de terceros
Se trata de las tiendas de aplicaciones de terceros en las que se obtienen actualizaciones automáticas de las apps instaladas cuando es necesario.

Exenciones del usuario al estado de hibernación

Si prevés que la hibernación afectará un caso de uso principal en la app, puedes solicitarle al usuario una exención de hibernación. Esta exención es útil para situaciones en las que el usuario espera que la app funcione principalmente en segundo plano, incluso sin que él interactúe con la app, por ejemplo, cuando esta realiza alguna de las siguientes acciones:

  • Informa de manera periódica la ubicación de los miembros de la familia para brindar seguridad familiar.
  • Sincroniza datos entre un dispositivo y el servidor de la app.
  • Se comunica con dispositivos inteligentes, como un TV.
  • Se vincula a dispositivos complementarios, como un reloj.

Para solicitar una exención, completa los pasos que se indican en las siguientes secciones.

Verifica si el usuario ya inhabilitó la hibernación para tu app

A fin de verificar si el usuario ya inhabilitó la hibernación para tu app, usa la API de getUnusedAppRestrictionsStatus().

Si deseas obtener más detalles acerca del uso de esta API en tu app, consulta el ejemplo de código de API que se incluye en esta página.

Pídele al usuario que inhabilite la hibernación de la app

Si el usuario aún no inhabilitó la hibernación para tu app, puedes enviarle una solicitud. Para hacerlo, completa estos pasos:

  1. Muestra una IU que explique al usuario por qué debe inhabilitar la hibernación para tu app.
  2. Invoca la API de createManageUnusedAppRestrictionsIntent(), como se muestra en el ejemplo de código de la API. Esta API crea un intent que carga la pantalla Información de apps en Configuración. Desde aquí, el usuario puede desactivar la hibernación para tu app.

    Es importante que llames a startActivityForResult(), no a startActivity(), cuando envíes este intent.

    Como se muestra en la Tabla 2, la ubicación y el nombre de la opción dependen de las características del dispositivo en el que está instalada la app:

    Tabla 2: Opción que inhabilita la hibernación para la app
    Características del dispositivo Página en la que aparece la opción Nombre de la opción que quieres desactivar
    Ejecuta Android 13 o una versión posterior Información de apps Pausar actividad en la app si no se usa
    Ejecuta Android 12 Información de apps Quitar permisos y liberar espacio
    Ejecuta Android 11 Información de apps > Permisos Quitar los permisos si la app no se usa
    Ejecuta desde Android 6.0 hasta Android 10, inclusive, y cuenta con la tecnología de los Servicios de Google Play Play app > Menú > Play Protect > Permisos de las apps que no se usan Quitar los permisos si la app no se usa

Ejemplo de código de API

En este ejemplo de código, se muestra cómo verificar si la hibernación está habilitada en tu app y la manera correcta de solicitar a los usuarios que la inhabiliten.

Kotlin

val future: ListenableFuture<Int> =
    PackageManagerCompat.getUnusedAppRestrictionsStatus(context)
future.addListener({ onResult(future.get()) }, ContextCompat.getMainExecutor(context))

fun onResult(appRestrictionsStatus: Int) {
  when (appRestrictionsStatus) {
    // Couldn't fetch status. Check logs for details.
    ERROR -> { }

    // Restrictions don't apply to your app on this device.
    FEATURE_NOT_AVAILABLE -> { }

    // The user has disabled restrictions for your app.
    DISABLED -> { }

    // If the user doesn't start your app for a few months, the system will
    // place restrictions on it. See the API_* constants for details.
    API_30_BACKPORT, API_30, API_31 -> handleRestrictions(appRestrictionsStatus)
  }
}

fun handleRestrictions(appRestrictionsStatus: Int) {
  // If your app works primarily in the background, you can ask the user
  // to disable these restrictions. Check if you have already asked the
  // user to disable these restrictions. If not, you can show a message to
  // the user explaining why permission auto-reset or app hibernation should be
  // disabled. Then, redirect the user to the page in system settings where they
  // can disable the feature.
  val intent = IntentCompat.createManageUnusedAppRestrictionsIntent(context, packageName)

  // You must use startActivityForResult(), not startActivity(), even if
  // you don't use the result code returned in onActivityResult().
  startActivityForResult(intent, REQUEST_CODE)
}

API de la plataforma heredada

El sistema operativo también incluye una API para interactuar con la función de hibernación. Sin embargo, la API solo funciona en dispositivos que ejecutan Android 11 o versiones posteriores, y no controla las funciones de hibernación que se portaron a versiones anteriores de Android. Por lo tanto, no te recomendamos que uses la API.

Si necesitas seguir usando la API de forma temporal para fines de compatibilidad, en la siguiente lista, se muestra cómo hacerlo:

Cómo invocar de forma manual el comportamiento de hibernación

Para probar cómo se comporta la app después de que el sistema la coloca en un estado de hibernación, sigue estos pasos:

  1. Habilita el comportamiento de hibernación en tu dispositivo (Solo para Android 12 y versiones posteriores):

    adb shell device_config put app_hibernation app_hibernation_enabled true
    
  2. Establece la cantidad de tiempo predeterminada que el sistema espera antes de entrar en hibernación. De esa manera, puedes restablecerla después de realizar las pruebas:

    threshold=$(adb shell device_config get permissions \
      auto_revoke_unused_threshold_millis2)
    
  3. Reduce la cantidad de tiempo que el sistema espera. En el siguiente ejemplo, se modifica el sistema de modo que tu app entre en hibernación solo un segundo después de que dejes de interactuar con ella:

    adb shell device_config put permissions \
      auto_revoke_unused_threshold_millis2 1000
    
  4. Espera a que finalice cualquier transmisión de inicio en el dispositivo de prueba ejecutando el siguiente comando:

    adb shell am wait-for-broadcast-idle
    

    Cuando finalicen las transmisiones, este comando mostrará el siguiente mensaje: All broadcast queues are idle!.

  5. Invoca el proceso de hibernación de apps de forma manual:

    adb shell cmd jobscheduler run -u 0 -f \
      com.google.android.permissioncontroller 2
    
  6. Confirma que la app esté en hibernación con uno de los siguientes métodos (Solo para Android 12 y versiones posteriores):

    • Observa que el dispositivo de prueba ahora muestra una notificación que indica que las apps que no se usan están en hibernación.
    • Ejecuta el siguiente comando:

      adb shell cmd app_hibernation get-state PACKAGE-NAME
      
  7. Restablece el tiempo predeterminado que espera el sistema antes de colocar la app en hibernación:

    adb shell device_config put permissions \
      auto_revoke_unused_threshold_millis2 $threshold