Los dispositivos Wear OS suelen usarse para experiencias de larga duración, como el seguimiento de un entrenamiento. Estas experiencias también pueden proporcionar información importante que le interesa al usuario y a la que necesita acceder rápidamente.
Esto presenta un desafío para la experiencia del usuario: si un usuario inicia una tarea y luego se desplaza a la cara de reloj, debería poder hacer lo siguiente:
- Seguir recibiendo actualizaciones importantes
- Volver a la tarea con un solo toque
Regresar a la app con el selector puede ser difícil, en especial cuando estás en movimiento, lo que genera una fricción innecesaria.
A partir de Wear OS 7, la solución es vincular una notificación continua con un
OngoingActivity o una notificación de actualización en vivo. Esto permite que el dispositivo muestre información sobre la actividad de larga duración en la interfaz de usuario, lo que habilita funciones como el ícono que se puede presionar en la parte inferior de la cara de reloj. Este indicador mantiene a los usuarios al tanto de la tarea en segundo plano y proporciona una forma de volver a la app con un solo toque.
Una actividad en curso o una actualización en vivo también mantienen tu app visible por más tiempo, lo que impide que el sistema vuelva a la cara de reloj después de un período de inactividad. Para obtener más información, consulta Cómo mantener tu app visible en Wear.
Usa una actividad en curso o una notificación de actualización en vivo para experiencias que probablemente duren más de un minuto o en casos en los que es probable que el usuario salga de tu app antes de que se complete la tarea.
Usos adecuados: entrenamientos registrados, temporizadores, seguimiento activo de viajes compartidos, grabación de voz más larga, como una reunión, y listas de compras que deben estar disponibles mientras el usuario está en una tienda
Usos inadecuados: grabación de mensajes de voz cortos, promociones, el estado de una app que se está actualizando y próximos eventos del calendario
Importante: Usar una
OngoingActivityo una actualización en vivo en estos casos es un requisito según los lineamientos de calidad de apps para Wear OS WO-V4.
Por ejemplo, en el caso de la app de entrenamiento, la información puede aparecer en la cara de reloj del usuario como un ícono de una persona corriendo que se puede presionar:
Figura 1: Indicador de actividad.
Una notificación continua también muestra información en la sección Recientes del selector global de aplicaciones. Esto proporciona otro lugar conveniente para que los usuarios vean el estado de su tarea y vuelvan a interactuar con la app:
Figura 2: Selector global.
Los siguientes son escenarios aptos para usar una notificación continua vinculada a una actividad en curso:
Figura 3: Temporizador: Realiza una cuenta regresiva de forma activa y finaliza cuando se pausa o detiene.
Figura 4: Navegación paso a paso: Anuncia las instrucciones para llegar a un destino. Finaliza cuando el usuario llega al destino o detiene la navegación.
Figura 5: Contenido multimedia: Reproduce música durante una sesión. Finaliza inmediatamente después de que el usuario pausa la sesión.
Wear crea actividades en curso automáticamente para las apps de contenido multimedia.
Consulta el codelab de Ongoing Activity para ver un ejemplo detallado de cómo crear actividades en curso para otros tipos de apps.
Configuración
Para comenzar a usar la API de Ongoing Activity en tu app, agrega las siguientes dependencias al archivo build.gradle de tu app:
dependencies {
implementation "androidx.wear:wear-ongoing:1.1.0"
implementation "androidx.core:core:1.19.0"
}
Cómo crear una actividad en curso
El proceso consta de tres pasos:
- Crea un
NotificationCompat.Builderestándar y configúralo como continuo. - Crea y configura un objeto
OngoingActivity, y pásale el compilador de notificaciones. - Aplica la actividad en curso al compilador de notificaciones y publica la notificación resultante.
Crea y configura la notificación
Comienza por crear un NotificationCompat.Builder. El paso clave es llamar a
setOngoing(true) para marcarla como una notificación continua. También puedes establecer otras propiedades de notificación en esta etapa, como el ícono pequeño y la categoría.
// Create a PendingIntent to pass to the notification builder val pendingIntent = PendingIntent.getActivity( this, 0, Intent(this, AlwaysOnActivity::class.java).apply { flags = Intent.FLAG_ACTIVITY_SINGLE_TOP }, PendingIntent.FLAG_UPDATE_CURRENT or PendingIntent.FLAG_IMMUTABLE, ) val notificationBuilder = NotificationCompat.Builder(this, CHANNEL_ID) .setContentTitle("Always On Service") .setContentText("Service is running in background") .setSmallIcon(R.drawable.animated_walk) // Category helps the system prioritize the ongoing activity .setCategory(NotificationCompat.CATEGORY_WORKOUT) .setContentIntent(pendingIntent) .setVisibility(NotificationCompat.VISIBILITY_PUBLIC) .setOngoing(true) // Important!
Crea la OngoingActivity
A continuación, crea una instancia de OngoingActivity con su compilador. El OngoingActivity.Builder requiere un Context, un ID de notificación y el NotificationCompat.Builder que creaste en el paso anterior.
Configura las propiedades clave que se mostrarán en las nuevas plataformas de la IU:
- Íconos animados y estáticos: Proporciona íconos que se muestran en la cara de reloj en los modos activo y ambiente.
- Intent táctil: Un
PendingIntentque lleva al usuario de vuelta a tu app cuando presiona el ícono de actividad en curso. Puedes volver a usar elpendingIndentcreado en el paso anterior.
val ongoingActivity = OngoingActivity.Builder(applicationContext, NOTIFICATION_ID, notificationBuilder) // Sets the icon that appears on the watch face in active mode. .setAnimatedIcon(R.drawable.animated_walk) // Sets the icon that appears on the watch face in ambient mode. .setStaticIcon(R.drawable.ic_walk) // Sets the tap target to bring the user back to the app. .setTouchIntent(pendingIntent) .build()
Aplica a la notificación y publica
El paso final es vincular la OngoingActivity con la notificación y, luego, publicarla. El método ongoingActivity.apply() modifica el compilador de notificaciones original
y agrega los datos necesarios para que el sistema pueda mostrarlo en
las plataformas adicionales. Después de aplicarlo, puedes compilar y publicar la notificación como de costumbre.
// This call modifies notificationBuilder to include the ongoing activity data. ongoingActivity.apply(applicationContext) // Post the notification. startForeground(NOTIFICATION_ID, notificationBuilder.build())
Agrega texto de estado dinámico al selector
El código anterior agrega el ícono que se puede presionar a la cara de reloj. Para proporcionar actualizaciones aún más
enriquecidas en tiempo real en la sección Recientes del selector, crea un
Status objeto y adjúntalo a tu OngoingActivity. Si no
proporcionas un Status, el sistema usará de forma predeterminada el texto de contenido de la notificación (establecido con setContentText()). Para mostrar texto dinámico, usa un
Status.Builder. Puedes definir una cadena de plantilla con marcadores de posición y proporcionar objetos Status.Part para completar esos marcadores de posición. El Status.Part puede ser dinámico, como un cronómetro o un temporizador.
En el siguiente ejemplo, se muestra cómo crear un estado que muestre "Run for [a stopwatch timer]":
// Define a template with placeholders for the activity type and the timer. val statusTemplate = "#type# for #time#" // Set the start time for a stopwatch. // Use SystemClock.elapsedRealtime() for time-based parts. val runStartTime = SystemClock.elapsedRealtime() val ongoingActivityStatus = Status.Builder() // Sets the template string. .addTemplate(statusTemplate) // Fills the #type# placeholder with a static text part. .addPart("type", Status.TextPart("Run")) // Fills the #time# placeholder with a stopwatch part. .addPart("time", Status.StopwatchPart(runStartTime)) .build()
Por último, vincula este Status a tu OngoingActivity llamando a setStatus()
en el OngoingActivity.Builder.
val ongoingActivity = OngoingActivity.Builder(applicationContext, NOTIFICATION_ID, notificationBuilder) // ... // Add the status to the OngoingActivity. .setStatus(ongoingActivityStatus) .build()
Personalizaciones adicionales
Además de Status, puedes personalizar tu actividad en curso o tus notificaciones de las siguientes maneras. Sin embargo, es posible que estas personalizaciones no se usen, según la implementación del OEM.
Notificación continua
- El conjunto de category determina la prioridad de la actividad en curso.
CATEGORY_CALL: Una llamada de voz o video entrante, o una solicitud de comunicación síncrona similarCATEGORY_NAVIGATION: Un mapa o navegación paso a pasoCATEGORY_TRANSPORT: Control de transporte de contenido multimedia para la reproducciónCATEGORY_ALARM: Una alarma o un temporizadorCATEGORY_WORKOUT: Un entrenamientoCATEGORY_LOCATION_SHARING: Categoría de uso compartido de ubicación temporalCATEGORY_STOPWATCH: Cronómetro
Actividad en curso
Ícono animado: Un vector en blanco y negro, preferentemente con un fondo transparente. Se muestra en la cara de reloj en el modo activo. Si no se proporciona, se usa el ícono de notificación predeterminado. El ícono de notificación predeterminado es diferente para cada aplicación.
Ícono estático: Un ícono vectorial con fondo transparente. Se muestra en la cara de reloj en el modo ambiente. Si no se configura el ícono animado, se usa el ícono estático en la cara de reloj en el modo activo. Si no se proporciona, se usa el ícono de notificación. Si no se establece ninguno, se arroja una excepción. (El selector de aplicaciones todavía utiliza el ícono de la app).
OngoingActivityStatus: Texto sin formato o un
Chronometer. Se muestra en la sección Recientes del selector de aplicaciones. Si no se proporciona, se usa la notificación "texto de contexto".Intent táctil: Se usa un
PendingIntentpara volver a la app si el usuario presiona el ícono de la actividad en curso. Se muestra en la cara de reloj o en el elemento del selector. Puede ser diferente del intent original que se usó para iniciar la app. Si no se proporciona, se usa el intent de contenido de la notificación. Si no se establece ninguno, se arroja una excepción.LocusId: Es un ID que asigna el acceso directo del selector al que corresponde la actividad en curso. Se muestra en el selector en la sección Recientes mientras la actividad está en curso. Si no se proporciona, el selector oculta todos los elementos de la app de la sección Recientes del mismo paquete y solo muestra la actividad en curso.ID de actividad en curso: Es un ID que se usa para desambiguar las llamadas a
fromExistingOngoingActivity()cuando una aplicación tiene más de una actividad en curso.
Actualiza una actividad en curso
Debes actualizar la actividad en curso para la notificación existente cuando necesites cambiar el estado, en lugar de crear una notificación y una actividad en curso nuevas. Para actualizar la actividad en curso y la notificación publicada, usa el objeto que creaste antes y llama a update(), como se muestra en el siguiente ejemplo:
ongoingActivity.update(context, newStatus)
En los casos en los que no es posible almacenar una referencia a la actividad en curso, existe un método estático para recuperarla. Sin embargo, esto es menos preferible:
OngoingActivity.recoverOngoingActivity(context) ?.update(context, newStatus)
Detén una actividad en curso
Cuando la app termina de ejecutarse como una actividad en curso, solo necesita cancelar la notificación continua.
También puedes cancelar la notificación o la actividad en curso cuando pase a primer plano y, luego, volver a crearlas cuando vuelvan a segundo plano, aunque esto no es obligatorio.
Pausa una actividad en curso
Si tu app tiene una acción explícita de detener, continúa con la actividad en curso después de reanudarla. En el caso de las apps sin una acción de detención explícita, finaliza la actividad cuando esté en pausa.
Consideraciones clave
Recuerda lo siguiente cuando trabajes con la API de Ongoing Activity:
Configura un ícono estático para tu actividad en curso, ya sea de forma explícita o como resguardo a través de la notificación. Si no lo haces, obtendrás una
IllegalArgumentException.Usa íconos vectoriales en blanco y negro con fondos transparentes.
Configura un intent táctil para tu actividad en curso, ya sea de forma explícita o como resguardo a través de la notificación. Si no lo haces, obtendrás una
IllegalArgumentException.Si la app tiene más de una actividad
MAIN LAUNCHERdeclarada en el manifiesto, publica un acceso directo dinámico y asócialo a tu actividad en curso conLocusId.
Publica notificaciones de contenido multimedia cuando se reproduce contenido multimedia en dispositivos Wear OS
Si se reproduce contenido multimedia en un dispositivo Wear OS, publica una notificación multimedia. Esto permite que el sistema cree la actividad en curso correspondiente.
Si usas Media3, la notificación se publica automáticamente. Si
creas tu notificación manualmente, debes usar
MediaStyleNotificationHelper.MediaStyle, y el
MediaSession correspondiente debe tener su actividad de la sesión propagada.
Recomendaciones para ti
- Nota: El texto del vínculo se muestra cuando JavaScript está desactivado
- Cómo crear una notificación {:#notification}
- Nuevas maneras de atraer usuarios de Wear OS con la API de Ongoing Activity
- Cómo crear una notificación expandible {:#expandable-notification}