Attività in corso

I dispositivi Wear OS vengono spesso utilizzati per esperienze di lunga durata, come il monitoraggio di un allenamento. Ciò presenta una sfida per l'esperienza utente: se un utente inizia un'attività e poi passa al quadrante, come fa a tornare indietro? Tornare all'app utilizzando l'avvio app può essere difficile, soprattutto quando si è in movimento, creando attrito non necessario.

La soluzione è abbinare una notifica in corso a un OngoingActivity. In questo modo, il dispositivo può visualizzare informazioni sull'attività di lunga durata nell'interfaccia utente, attivando funzionalità come l'icona selezionabile nella parte inferiore del quadrante. In questo modo gli utenti sono consapevoli dell'attività in background e possono tornare all'app con un solo tocco.

Ad esempio, in questa app di allenamento, le informazioni possono essere visualizzate sul quadrante dello smartwatch dell'utente come icona di corsa selezionabile:

icona-corsa

Figura 1. Indicatore di attività.

Una notifica continua mostra anche informazioni nella sezione Recenti del launcher delle app globale. In questo modo, gli utenti hanno un altro posto comodo per vedere lo stato dell'attività e interagire di nuovo con l'app:

avvio app

Figura 2. Avvio app globale.

Di seguito sono riportate alcune situazioni in cui è consigliabile utilizzare una notifica continua legata a un'attività in corso:

timer

Figura 3. Timer:esegue attivamente il conto alla rovescia e termina quando il timer viene messo in pausa o arrestato.

mappa

Figura 4. Indicazioni stradali passo passo: annuncia le indicazioni per una destinazione. Termina quando l'utente raggiunge la destinazione o interrompe la navigazione.

musica

Figura 5. Contenuti multimediali:riproduce musica durante una sessione. Termina immediatamente dopo che l'utente mette in pausa la sessione.

Wear crea automaticamente attività in corso per le app multimediali.

Per un esempio dettagliato di creazione di attività in corso per altri tipi di app, consulta il codelab Attività in corso.

Configura

Per iniziare a utilizzare l'API Ongoing Activity nella tua app, aggiungi le seguenti dipendenze al file build.gradle della tua app:

dependencies {
  implementation "androidx.wear:wear-ongoing:1.1.0"
  implementation "androidx.core:core:1.17.0"
}

Creare un'attività continua

La procedura prevede tre passaggi:

  1. Crea un NotificationCompat.Builder standard e configuralo come in corso.
  2. Crea e configura un oggetto OngoingActivity, passandogli il generatore di notifiche.
  3. Applica l'attività in corso al generatore di notifiche e pubblica la notifica risultante.

Crea e configura la notifica

Inizia creando un NotificationCompat.Builder. Il passaggio chiave è chiamare setOngoing(true) per contrassegnarla come notifica costante. In questa fase puoi anche impostare altre proprietà di notifica, come l'icona piccola e la categoria.

// 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 OngoingActivity

Successivamente, crea un'istanza di OngoingActivity utilizzando il relativo builder. OngoingActivity.Builder richiede un Context, un ID notifica e l'NotificationCompat.Builder che hai creato nel passaggio precedente.

Configura le proprietà chiave che verranno visualizzate nelle nuove superfici dell'interfaccia utente:

  • Icone animate e statiche: fornisci icone visualizzate sul quadrante dell'orologio in modalità attiva e Ambient.
  • Intent di tocco: un PendingIntent che riporta l'utente alla tua app quando tocca l'icona dell'attività in corso. Puoi riutilizzare pendingIndent creato nel passaggio precedente.

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()

Applica alla notifica e al post

Il passaggio finale consiste nel collegare il OngoingActivity alla notifica e poi pubblicarla. Il metodo ongoingActivity.apply() modifica il builder di notifiche originale, aggiungendo i dati necessari in modo che il sistema possa visualizzarli sulle superfici aggiuntive. Dopo averlo applicato, puoi creare e pubblicare la notifica come di consueto.

// This call modifies notificationBuilder to include the ongoing activity data.
ongoingActivity.apply(applicationContext)

// Post the notification.
startForeground(NOTIFICATION_ID, notificationBuilder.build())

Aggiungere testo di stato dinamico ad Avvio app

Il codice precedente aggiunge l'icona toccabile al quadrante. Per fornire aggiornamenti in tempo reale ancora più ricchi nella sezione Recenti dell'app di avvio, crea un oggetto Status e allegalo al tuo OngoingActivity . Se non fornisci un Status personalizzato, il sistema utilizza per impostazione predefinita il testo dei contenuti della notifica (impostato utilizzando setContentText()).

Per visualizzare il testo dinamico, utilizza un Status.Builder. Puoi definire una stringa modello con segnaposto e fornire Status.Part oggetti per riempire questi segnaposto. Il Status.Part può essere dinamico, ad esempio un cronometro o un timer .

Il seguente esempio mostra come creare uno stato che visualizzi "Corri per [un cronometro]":

// 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()

Infine, collega questo Status al tuo OngoingActivity chiamando il numero setStatus() sul OngoingActivity.Builder.

val ongoingActivity =
    OngoingActivity.Builder(applicationContext, NOTIFICATION_ID, notificationBuilder)
        // ...
        // Add the status to the OngoingActivity.
        .setStatus(ongoingActivityStatus)
        .build()

Personalizzazioni aggiuntive

Oltre a Status, puoi personalizzare le tue attività o notifiche in corso nei seguenti modi. Tuttavia, queste personalizzazioni potrebbero non essere utilizzate, a seconda dell'implementazione dell'OEM.

Notifica continua

  • Il set di categorie determina la priorità dell'attività in corso.
    • CATEGORY_CALL: una chiamata vocale o video in arrivo o una richiesta di comunicazione sincrona simile
    • CATEGORY_NAVIGATION: una mappa o la navigazione passo passo
    • CATEGORY_TRANSPORT: controllo del trasporto dei contenuti multimediali per la riproduzione
    • CATEGORY_ALARM: una sveglia o un timer
    • CATEGORY_WORKOUT: un allenamento
    • CATEGORY_LOCATION_SHARING: categoria di condivisione temporanea della posizione
    • CATEGORY_STOPWATCH: cronometro

Attività in corso

  • Icona animata: un vettore in bianco e nero, preferibilmente con uno sfondo trasparente. Viene visualizzato sul quadrante in modalità attiva. Se l'icona animata non viene fornita, viene utilizzata l'icona di notifica predefinita. L'icona di notifica predefinita è diversa per ogni applicazione.

  • Icona statica:un'icona vettoriale con sfondo trasparente. Viene visualizzato sul quadrante in modalità Ambient. Se l'icona animata non è impostata, viene utilizzata l'icona statica sul quadrante in modalità attiva. Se non viene fornito, viene utilizzata l'icona di notifica. Se non è impostato nessuno dei due, viene generata un'eccezione. (Avvio app utilizza ancora l'icona dell'app.)

  • OngoingActivityStatus:testo normale o Chronometer. Viene visualizzato nella sezione Recenti di Avvio app. Se non viene fornito, viene utilizzato il "testo contestuale" della notifica.

  • Intent di tocco:un PendingIntent utilizzato per tornare all'app se l'utente tocca l'icona dell'attività in corso. Visualizzati sul quadrante o nell'elemento del launcher. Può essere diverso dall'intent originale utilizzato per avviare l'app. Se non viene fornito, viene utilizzato l'intent dei contenuti della notifica. Se non è impostato nessuno dei due, viene generata un'eccezione.

  • LocusId: ID che assegna la scorciatoia del launcher a cui corrisponde l'attività in corso. Viene visualizzato nell'avvio app nella sezione Recenti mentre l'attività è in corso. Se non viene fornito, il launcher nasconde tutti gli elementi delle app nella sezione Recenti dello stesso pacchetto e mostra solo l'attività in corso.

  • ID attività in corso:ID utilizzato per distinguere le chiamate a fromExistingOngoingActivity() quando un'applicazione ha più di un'attività in corso.

Aggiornare un'attività continua

Nella maggior parte dei casi, gli sviluppatori creano una nuova notifica continua e una nuova attività continua quando devono aggiornare i dati sullo schermo. Tuttavia, l'API Ongoing Activity offre anche metodi helper per aggiornare un OngoingActivity se vuoi conservare un'istanza anziché ricrearla.

Se l'app è in esecuzione in background, può inviare aggiornamenti all'API Ongoing Activity. Tuttavia, non farlo troppo spesso, perché il metodo di aggiornamento ignora le chiamate troppo vicine tra loro. Alcuni aggiornamenti al minuto sono ragionevoli.

Per aggiornare l'attività in corso e la notifica pubblicata, utilizza l'oggetto che hai creato in precedenza e chiama update(), come mostrato nell'esempio seguente:

ongoingActivity.update(context, newStatus)

Per comodità, esiste un metodo statico per creare un'attività continua.

OngoingActivity.recoverOngoingActivity(context)
               .update(context, newStatus)

Interrompere un'attività in corso

Quando l'app ha terminato l'esecuzione come attività in corso, deve solo annullare la notifica in corso.

Puoi anche scegliere di annullare la notifica o l'attività in corso quando viene portata in primo piano, quindi ricrearla quando torna in background, ma non è obbligatorio.

Mettere in pausa un'attività in corso

Se la tua app ha un'azione di interruzione esplicita, continua l'attività in corso dopo che è stata riattivata. Per un'app senza un'azione di interruzione esplicita, termina l'attività quando viene sospesa.

Best practice

Quando utilizzi l'API Ongoing Activity, ricorda quanto segue:

  • Imposta un'icona statica per l'attività in corso, in modo esplicito o come fallback utilizzando la notifica. In caso contrario, riceverai un IllegalArgumentException.

  • Utilizza icone vettoriali in bianco e nero con sfondi trasparenti.

  • Imposta un intent di tocco per l'attività in corso, esplicitamente o come fallback utilizzando la notifica. In caso contrario, riceverai un IllegalArgumentException.

  • Se la tua app ha più di un'attività MAIN LAUNCHER dichiarata nel manifest, pubblica una scorciatoia dinamica e associala alla tua attività in corso utilizzando LocusId.

Pubblicare notifiche multimediali durante la riproduzione di contenuti multimediali sui dispositivi Wear OS

Se i contenuti multimediali vengono riprodotti su un dispositivo Wear OS, pubblica una notifica multimediale. In questo modo, il sistema può creare l'attività corrispondente.

Se utilizzi Media3, la notifica viene pubblicata automaticamente. Se crei la notifica manualmente, deve utilizzare MediaStyleNotificationHelper.MediaStyle e l'MediaSession corrispondente deve avere l'attività della sessione compilata.