Apps siempre encendidas y modo ambiente del sistema

Wear OS controla automáticamente el cambio al modo de bajo consumo de una app activa cuando un usuario deja de usar el reloj. Eso se denomina modo ambiente del sistema. La app se reanuda después de que el usuario interactúa con el reloj si se cumple alguna de las siguientes condiciones:

  • La interacción del usuario ocurre dentro de un período determinado (antes del tiempo de espera).
  • La app declara y comenzó una actividad en curso.

Para casos de uso específicos, como un usuario que desea ver la frecuencia cardíaca y el ritmo durante una carrera, también puedes controlar lo que se muestra en el modo ambiente del sistema. Las apps para Wear OS que se ejecutan en los modos interactivo y ambiente se denominan apps siempre activas.

Hacer que una app sea visible constantemente afecta la duración de la batería, por lo que debes tener en cuenta ese impacto cuando agregues esta función a tu app.

Cómo configurar tu proyecto

Para admitir el modo ambiente, sigue estos pasos:

  1. Crea o actualiza tu proyecto según la configuración de la página Cómo crear y ejecutar una app para wearables.
  2. (Solo es necesario en Wear OS 4 o versiones anteriores). Agrega el permiso WAKE_LOCK al archivo de manifiesto de Android:
<uses-permission android:name="android.permission.WAKE_LOCK" android:maxSdkVersion="33"/>

Cómo habilitar el modo siempre activo

A partir de Wear OS 6, las apps con targetSdkVersion establecido en 36 o más están siempre activas de forma predeterminada. Estas apps permanecen visibles durante el modo ambiente del sistema durante un período limitado sin necesidad de configuración. Si el targetSdkVersion de tu app es inferior a 36, o si tu app debe ejecutarse en Wear OS 5 o versiones anteriores, usa la clase AmbientLifecycleObserver para que tu app esté siempre activa.

Cómo reaccionar a los eventos del modo ambiente con la clase AmbientLifecycleObserver

Las apps también pueden usar la clase AmbientLifecycleObserver para reaccionar directamente a los eventos del modo ambiente:

  1. Implementa la interfaz AmbientLifecycleObserver.AmbientLifecycleCallback, como en el siguiente ejemplo. En esta etapa, los métodos están vacíos, pero más adelante en la guía se proporcionan detalles sobre los cambios que debes realizar en la visualización para entrar al modo ambiente y salir de él.

    Kotlin

    val ambientCallback = object : AmbientLifecycleObserver.AmbientLifecycleCallback {
        override fun onEnterAmbient(ambientDetails: AmbientLifecycleObserver.AmbientDetails) {
        // ... Called when moving from interactive mode into ambient mode.
        }
    
        override fun onExitAmbient() {
        // ... Called when leaving ambient mode, back into interactive mode.
        }
    
        override fun onUpdateAmbient() {
        // ... Called by the system in order to allow the app to periodically
        // update the display while in ambient mode. Typically the system will
        // call this every 60 seconds.
        }
    }
  2. Crea un AmbientLifecycleObserver y registra el observador. Por lo general, se usa en onCreate() o en el elemento componible de nivel superior si se usa Compose para Wear OS, para permitir que se habilite el comportamiento siempre activo durante todo el ciclo de vida de la actividad.

    Kotlin

    private val ambientObserver = AmbientLifecycleObserver(activity, callback)
    
    override fun onCreate(savedInstanceState: Bundle) {
      super.onCreate(savedInstanceState)
      lifecycle.addObserver(observer)
    
      // ...
    }
  3. Quita el observador llamando a removeObserver() cuando ya no se requiera el comportamiento siempre activo. Por ejemplo, puedes llamar a este método en el método onDestroy() de tu actividad.

Actualiza el texto de la hora con el widget TimeText

A partir de Wear OS 6, el widget TimeText es compatible con el modo ambiente. Si tu app solo necesita actualizar un texto de hora cada minuto durante el modo ambiente, puedes usar el widget TimeText sin usar AmbientLifecycleObserver.

Las apps siempre activas pueden pasar a segundo plano

A partir de Wear OS 5, el sistema mueve las apps siempre activas al segundo plano después de que sean visibles en el modo ambiente durante un período determinado. Los usuarios pueden configurar el tiempo de espera en la configuración del sistema.

Si tu app siempre activa muestra información sobre una tarea en curso del usuario, como la reproducción de música o una sesión de entrenamiento, te recomendamos que mantengas visible la actividad en curso hasta que finalice la tarea. Para ello, usa la API de Ongoing Activity para publicar una notificación continua vinculada a tu actividad siempre activa.

Para que el sistema reconozca la actividad en curso, el intent de toque de la notificación en curso debe apuntar a tu actividad siempre activa, como se muestra en el siguiente fragmento de código:

// Create a pending intent that point to your always-on activity
val touchIntent =
    PendingIntent.getActivity(
        context,
        0,
        Intent(context, MyAlwaysOnActivity::class.java),
        PendingIntent.FLAG_MUTABLE or PendingIntent.FLAG_UPDATE_CURRENT
    )

val notificationBuilder =
    NotificationCompat.Builder(this, CHANNEL_ID)
    // ...
    .setOngoing(true)

val ongoingActivity =
    OngoingActivity.Builder(
        applicationContext, NOTIFICATION_ID, notificationBuilder
    )
    // ...
    .setTouchIntent(touchIntent)
    .build()

ongoingActivity.apply(applicationContext)

notificationManager.notify(
    NOTIFICATION_ID,
    notificationBuilder.build()
)

Cómo modificar la experiencia del usuario en el modo ambiente

De forma predeterminada, cuando se implementa el comportamiento siempre activo, la pantalla no cambia su apariencia cuando el reloj entra en el modo ambiente. Puedes modificar este comportamiento anulando los métodos en AmbientLifecycleCallback.

Para ahorrar energía, haz lo siguiente:

  • Ilumina menos píxeles. Considera mostrar solo la información crítica en el modo ambiente y proporciona más detalles cuando el usuario entre en el modo interactivo.
  • Mantén al menos el 85% de la pantalla en negro, quita los rellenos y usa contornos para los botones y los íconos grandes.
  • Evita mostrar información irrelevante, como imágenes de fondo y desarrollo de la marca no funcionales.
  • Mantén los elementos en la misma posición en los modos activo y siempre activo, y muestra la hora en todo momento.
  • Ajusta el contenido para que se actualice con menos frecuencia. Por ejemplo, muestra los cronómetros al minuto y no al segundo más cercano.
  • Quita o muestra la IU de marcador de posición para el contenido alfanumérico que se actualiza con frecuencia, como la distancia o la hora.
  • Quita los indicadores de progreso que se actualizan con frecuencia, como los anillos de cuenta regresiva y las sesiones multimedia.
  • Cuando ingreses al modo siempre activo, si el usuario estaba en una pantalla de configuración en tu app, considera mostrar una pantalla más relevante en tu app.
  • En el objeto AmbientDetails que se pasa a onEnterAmbient(), haz lo siguiente:
    • Si se configura deviceHasLowBitAmbient, inhabilita el suavizado de contorno siempre que sea posible.
    • Si se configura burnInProtectionRequired, cambia la visualización de forma periódica y evita las áreas blancas sólidas.
  • Evita ejecutar animaciones continuas durante el modo ambiente. A partir de Wear OS 5.1, es posible que los animadores dejen de ejecutarse durante el modo ambiente.

Lista de tareas para una visualización sin interrupciones

Es posible que haya situaciones en las que desees tener el máximo control sobre la pantalla a medida que el dispositivo pasa por diferentes estados, por ejemplo, cuando una app de entrenamiento quiere evitar que la cara de reloj aparezca en la pantalla durante un entrenamiento. En estos casos, haz lo siguiente:

  1. Implementa la interfaz AmbientLifecycleObserver.AmbientLifecycleCallback.
  2. Crea un nuevo diseño de bajo consumo para usarlo cuando el dispositivo esté en el modo ambiente del sistema.
  3. Durante el entrenamiento, implementa una actividad en curso.

Para ver un ejemplo de cómo se puede lograr esto, consulta la muestra de ejercicio basada en Compose en GitHub, que usa el elemento componible AmbientAware de la biblioteca Horologist.