Laufende Aktivität

Bei Wear OS wird durch das Koppeln einer laufenden Aktivität mit einer laufenden Benachrichtigung diese Benachrichtigung weiteren Oberflächen der Wear OS-Benutzeroberfläche hinzugefügt. So können Nutzer länger andauernde Aktivitäten weiter nutzen.

Laufende Benachrichtigungen werden in der Regel verwendet, um darauf hinzuweisen, dass eine Benachrichtigung eine Hintergrundaufgabe hat, mit der der Nutzer aktiv interagiert oder in irgendeiner Weise ansteht und daher das Gerät belegt.

Ein Wear OS-Nutzer könnte beispielsweise mit einer Workout-App einen Lauf aus einer Aktivität aufzeichnen und dann diese App verlassen, um eine andere Aufgabe zu starten. Wenn der Nutzer die Trainings-App verlässt, wechselt die App zu einer fortlaufenden Benachrichtigung, die mit einigen Hintergrundarbeiten verknüpft ist, um den Nutzer über seinen Lauf auf dem Laufenden zu halten. Die Benachrichtigung bietet dem Nutzer Updates und eine einfache Möglichkeit, wieder auf die App zuzugreifen.

Um die Benachrichtigung anzuzeigen, muss der Nutzer jedoch in die Benachrichtigungsleiste unter dem Zifferblatt wischen und die richtige Benachrichtigung finden. Dies ist nicht so praktisch wie auf anderen Oberflächen.

Mit der Ongoing Activity API können über die fortlaufende Benachrichtigung einer App Informationen auf mehreren neuen, praktischen Oberflächen unter Wear OS verfügbar gemacht werden, um den Nutzer aufrechtzuerhalten.

In dieser Trainings-App können die Informationen beispielsweise auf dem Zifferblatt des Nutzers als antippbares Laufsymbol erscheinen:

Laufsymbol

Abbildung 1: Aktivitätsanzeige.

Im Abschnitt Recents des globalen App Launchers werden auch alle laufenden Aktivitäten aufgeführt:

launcher

Abbildung 2: Globaler Launcher

In den folgenden Situationen empfiehlt es sich, eine fortlaufende Benachrichtigung für eine laufende Aktivität zu verwenden:

timer

Abbildung 3: Timer:Er zählt die Zeit aktiv und endet, wenn der Timer pausiert oder gestoppt wird.

Karte

Abbildung 4: Schritt-für-Schritt-Navigation:Kündigt die Route zu einem Ziel an. Sie endet, wenn der Nutzer das Ziel erreicht oder die Navigation beendet.

Musik

Abbildung 5: Medien:Spielt während einer Sitzung Musik ab. Sie endet sofort, nachdem der Nutzer die Sitzung angehalten hat.

Wear erstellt automatisch laufende Aktivitäten für Medien-Apps.

Im Codelab zu laufenden Aktivitäten findest du ein ausführliches Beispiel zum Erstellen fortlaufender Aktivitäten für andere Arten von Apps.

Einrichten

Wenn Sie die Ongoing Activity API in Ihrer App verwenden möchten, fügen Sie der Datei build.gradle Ihrer App die folgenden Abhängigkeiten hinzu:

dependencies {
  implementation "androidx.wear:wear-ongoing:1.0.0"
  // Includes LocusIdCompat and new Notification categories for Ongoing Activity.
  implementation "androidx.core:core:1.6.0"
}

Laufende Aktivität starten

Erstellen Sie zuerst eine fortlaufende Benachrichtigung und dann eine laufende Aktivität.

Aktive Benachrichtigung erstellen

Eine laufende Aktivität ist eng mit einer laufenden Benachrichtigung verbunden. Sie arbeiten zusammen, um Nutzer über eine Aufgabe zu informieren, mit der der Nutzer aktiv beschäftigt ist, oder über eine Aufgabe, die in irgendeiner Weise noch aussteht und daher das Gerät belegt.

Du musst eine laufende Aktivität mit einer laufenden Benachrichtigung koppeln. Das Verknüpfen deiner laufenden Aktivitäten mit einer Benachrichtigung bietet unter anderem die folgenden Vorteile:

  • Benachrichtigungen sind das Fallback auf Geräten, die keine laufenden Aktivitäten unterstützen. Die Benachrichtigung ist die einzige Oberfläche, die von Ihrer App angezeigt wird, während sie im Hintergrund ausgeführt wird.
  • Unter Android 11 und höher blendet Wear OS die Benachrichtigung in der Benachrichtigungsleiste aus, wenn die App als laufende Aktivität auf zusätzlichen Oberflächen sichtbar ist.
  • Die aktuelle Implementierung verwendet Notification selbst als Kommunikationsmechanismus.

Erstellen Sie mit Notification.Builder.setOngoing eine laufende Benachrichtigung.

Laufende Aktivität starten

Wenn Sie eine fortlaufende Benachrichtigung haben, erstellen Sie eine laufende Aktivität, wie im folgenden Beispiel gezeigt. Sehen Sie sich die enthaltenen Kommentare an, um das Verhalten der einzelnen Unterkünfte zu verstehen.

Kotlin

var notificationBuilder = NotificationCompat.Builder(this, CHANNEL_ID)
      …
      .setSmallIcon(..)
      .setOngoing(true)

val ongoingActivityStatus = Status.Builder()
    // Sets the text used across various surfaces.
    .addTemplate(mainText)
    .build()

val ongoingActivity =
    OngoingActivity.Builder(
        applicationContext, NOTIFICATION_ID, notificationBuilder
    )
        // Sets the animated icon that will appear on the watch face in
        // active mode.
        // If it isn't set, the watch face will use the static icon in
        // active mode.
        .setAnimatedIcon(R.drawable.ic_walk)
        // Sets the icon that will appear on the watch face in ambient mode.
        // Falls back to Notification's smallIcon if not set.
        // If neither is set, an Exception is thrown.
        .setStaticIcon(R.drawable.ic_walk)
        // Sets the tap/touch event so users can re-enter your app from the
        // other surfaces.
        // Falls back to Notification's contentIntent if not set.
        // If neither is set, an Exception is thrown.
        .setTouchIntent(activityPendingIntent)
        // Here, sets the text used for the Ongoing Activity (more
        // options are available for timers and stopwatches).
        .setStatus(ongoingActivityStatus)
        .build()

ongoingActivity.apply(applicationContext)

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

Java

NotificationCompat.Builder notificationBuilder = NotificationCompat.Builder(this, CHANNEL_ID)
      …
      .setSmallIcon(..)
      .setOngoing(true);

OngoingActivityStatus ongoingActivityStatus = OngoingActivityStatus.Builder()
    // Sets the text used across various surfaces.
    .addTemplate(mainText)
    .build();

OngoingActivity ongoingActivity =
    OngoingActivity.Builder(
        applicationContext, NOTIFICATION_ID, notificationBuilder
    )
        // Sets the animated icon that will appear on the watch face in
        // active mode.
        // If it isn't set, the watch face will use the static icon in
        // active mode.
        .setAnimatedIcon(R.drawable.ic_walk)
        // Sets the icon that will appear on the watch face in ambient mode.
        // Falls back to Notification's smallIcon if not set.
        // If neither is set, an Exception is thrown.
        .setStaticIcon(R.drawable.ic_walk)
        // Sets the tap/touch event so users can re-enter your app from the
        // other surfaces.
        // Falls back to Notification's contentIntent if not set.
        // If neither is set, an Exception is thrown.
        .setTouchIntent(activityPendingIntent)
        // Here, sets the text used for the Ongoing Activity (more
        // options are available for timers and stopwatches).
        .setStatus(ongoingActivityStatus)
        .build();

ongoingActivity.apply(applicationContext);

notificationManager.notify(NOTIFICATION_ID, builder.build());

Die folgenden Schritte heben den wichtigsten Teil des vorherigen Beispiels hervor:

  1. Rufen Sie .setOngoing(true) für NotificationCompat.Builder auf und legen Sie optionale Felder fest.

  2. Erstellen Sie eine OngoingActivityStatus oder eine andere Statusoption, wie im folgenden Abschnitt beschrieben, um den Text darzustellen.

  3. Erstelle eine OngoingActivity und lege eine Benachrichtigungs-ID fest.

  4. Rufen Sie apply() für OngoingActivity mit dem Kontext auf.

  5. Rufe notificationManager.notify() auf und übergib dieselbe Benachrichtigungs-ID, die in der laufenden Aktivität festgelegt ist, um sie zu verknüpfen.

Status

Mit der Status kannst du dem Nutzer den aktuellen Livestatus der OngoingActivity auf neuen Oberflächen wie Letzte Aufrufe des Launchers anzeigen. Verwenden Sie zur Nutzung des Features die abgeleitete Status.Builder-Klasse.

In den meisten Fällen müssen Sie nur eine Vorlage hinzufügen, die den Text darstellt, der im Bereich Recents des App Launchers angezeigt werden soll.

Sie können dann anpassen, wie Text mit Spans angezeigt wird. Verwenden Sie dazu die Methode addTemplate() und geben Sie beliebige dynamische Teile des Textes als Status.Part an.

Das folgende Beispiel zeigt, wie Sie das Wort „Uhrzeit“ rot anzeigen lassen können. Im Beispiel wird ein Status.StopwatchPart verwendet, um im Bereich Recents des App Launchers eine Stoppuhr darzustellen.

Kotlin

val htmlStatus =
        "<p>The <font color=\"red\">time</font> on your current #type# is #time#.</p>"

val statusTemplate =
        Html.fromHtml(
                htmlStatus,
                Html.FROM_HTML_MODE_COMPACT
        )

// Creates a 5 minute timer.
// Note the use of SystemClock.elapsedRealtime(), not System.currentTimeMillis().
val runStartTime = SystemClock.elapsedRealtime() + TimeUnit.MINUTES.toMillis(5)

val status = new Status.Builder()
   .addTemplate(statusTemplate)
   .addPart("type", Status.TextPart("run"))
   .addPart("time", Status.StopwatchPart(runStartTime)
   .build()

Java

String htmlStatus =
        "<p>The <font color=\"red\">time</font> on your current #type# is #time#.</p>";

Spanned statusTemplate =
        Html.fromHtml(
                htmlStatus,
                Html.FROM_HTML_MODE_COMPACT
        );

// Creates a 5 minute timer.
// Note the use of SystemClock.elapsedRealtime(), not System.currentTimeMillis().
Long runStartTime = SystemClock.elapsedRealtime() + TimeUnit.MINUTES.toMillis(5);

Status status = new Status.Builder()
   .addTemplate(statusTemplate)
   .addPart("type", new Status.TextPart("run"))
   .addPart("time", new Status.StopwatchPart(runStartTime)
   .build();

Wenn Sie auf einen Teil in der Vorlage verweisen möchten, verwenden Sie den von # umgebenen Namen. Um # in der Ausgabe zu erzeugen, verwenden Sie ## in der Vorlage.

Im vorherigen Beispiel wird mit HTMLCompat ein CharSequence generiert, das an die Vorlage übergeben werden kann. Dies ist einfacher als die manuelle Definition eines Spannable-Objekts.

Zusätzliche Anpassungen

Neben Status können Sie Ihre laufenden Aktivitäten oder Benachrichtigungen so anpassen. Je nach Implementierung des OEM werden diese Anpassungen jedoch möglicherweise nicht verwendet.

Laufende Benachrichtigung

  • Die festgelegte Kategorie bestimmt die Priorität der laufenden Aktivität.
    • CATEGORY_CALL: Ein eingehender Sprach- oder Videoanruf oder eine ähnliche synchrone Kommunikationsanfrage
    • CATEGORY_NAVIGATION:Karte oder detaillierte Routenführung
    • CATEGORY_TRANSPORT:Medientransport für die Wiedergabe
    • CATEGORY_ALARM:Wecker oder Timer
    • CATEGORY_WORKOUT:ein Training (neue Kategorie)
    • CATEGORY_LOCATION_SHARING:temporäre Standortfreigabe (neue Kategorie)
    • CATEGORY_STOPWATCH:Stoppuhr (neue Kategorie)

Laufende Aktivität

  • Animiertes Symbol:Ein Schwarz-Weiß-Vektor, vorzugsweise mit transparentem Hintergrund. Wird im Aktivmodus auf dem Zifferblatt angezeigt. Wenn das animierte Symbol nicht angegeben ist, wird das Standardbenachrichtigungssymbol verwendet. Das Standardsymbol für Benachrichtigungen unterscheidet sich je nach Anwendung.

  • Statisches Symbol:Vektorsymbol mit transparentem Hintergrund. wird auf dem Zifferblatt im Inaktivmodus angezeigt. Wenn das animierte Symbol nicht festgelegt ist, wird das statische Symbol im Aktivmodus auf dem Zifferblatt verwendet. Ist dies nicht angegeben, wird das Benachrichtigungssymbol verwendet. Wenn keines von beiden festgelegt ist, wird eine Ausnahme ausgelöst. Im App Launcher wird weiterhin das App-Symbol verwendet.

  • OngoingActivityStatus:Nur Text oder Chronometer Sie werden im Bereich Letzte Aufrufe des App Launchers angezeigt. Wenn keine Angabe erfolgt, wird die Benachrichtigung "Kontexttext" verwendet.

  • Touch-Intent: Ein PendingIntent, mit dem zurück zur App gewechselt wird, wenn der Nutzer auf das Symbol für laufende Aktivität tippt. Wird auf dem Zifferblatt oder im Launcher-Element angezeigt. Er kann sich vom ursprünglichen Intent unterscheiden, mit dem die App gestartet wurde. Wenn er nicht angegeben ist, wird der Inhalts-Intent der Benachrichtigung verwendet. Wenn keiner der beiden Parameter festgelegt ist, wird eine Ausnahme ausgelöst.

  • LocusId: ID, die die Launcher-Verknüpfung zuweist, der die aktuelle Aktivität entspricht. Wird während der Aktivität auf dem Launcher im Bereich Letzte Aufrufe angezeigt. Wenn nicht angegeben, blendet der Launcher alle App-Elemente im Abschnitt Recents (Letzte) im selben Paket aus und zeigt nur die laufende Aktivität an.

  • ID der laufenden Aktivität:ID, die verwendet wird, um Aufrufe von fromExistingOngoingActivity() zu unterscheiden, wenn in einer App mehr als eine laufende Aktivität vorhanden ist.

Laufende Aktivität aktualisieren

In den meisten Fällen erstellen Entwickler eine neue fortlaufende Benachrichtigung und eine neue laufende Aktivität, wenn sie die Daten auf dem Bildschirm aktualisieren müssen. Die Ongoing Activity API bietet jedoch auch Hilfsmethoden zum Aktualisieren eines OngoingActivity, wenn Sie eine Instanz beibehalten möchten, anstatt sie neu zu erstellen.

Wenn die App im Hintergrund ausgeführt wird, kann sie Aktualisierungen an die Ongoing Activity API senden. Sie sollten dies jedoch nicht zu oft tun, da die Aktualisierungsmethode Aufrufe ignoriert, die zu nah beieinander liegen. Einige Aktualisierungen pro Minute sind angemessen.

Um die laufende Aktivität und die gesendete Benachrichtigung zu aktualisieren, verwenden Sie das zuvor erstellte Objekt und rufen Sie update() auf, wie im folgenden Beispiel gezeigt:

Kotlin

ongoingActivity.update(context, newStatus)

Java

ongoingActivity.update(context, newStatus);

Der Einfachheit halber gibt es eine statische Methode zum Erstellen einer fortlaufenden Aktivität.

Kotlin

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

Java

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

Laufende Aktivität beenden

Wenn die Ausführung der App als laufende Aktivität beendet ist, muss nur die laufende Benachrichtigung abgebrochen werden.

Sie können auch die Benachrichtigung oder die laufende Aktivität im Vordergrund abbrechen und sie dann neu erstellen, wenn Sie in den Hintergrund zurückkehren. Dies ist jedoch nicht erforderlich.

Laufende Aktivität pausieren

Wenn für Ihre App eine explizite Stoppaktion festgelegt ist, setzen Sie die laufende Aktivität nach dem Aufheben der Pausierung fort. Bei einer App ohne explizite Stoppaktion beenden Sie die Aktivität, wenn sie pausiert wird.

Best Practices

Beachten Sie Folgendes, wenn Sie mit der Ongoing Activity API arbeiten:

  • Rufe zuerst ongoingActivity.apply(context) auf, bevor du notificationManager.notify(...) aufrufst.
  • Lege ein statisches Symbol für deine laufende Aktivität fest, entweder explizit oder als Fallback über die Benachrichtigung. Andernfalls erhalten Sie ein IllegalArgumentException.

  • Verwenden Sie schwarz-weiße Vektorsymbole mit transparentem Hintergrund.

  • Lege einen Touch-Intent für deine laufende Aktivität fest, entweder explizit oder als Fallback mithilfe der Benachrichtigung. Andernfalls erhalten Sie ein IllegalArgumentException.

  • Verwende für NotificationCompat die Core AndroidX-Bibliothek core:1.5.0-alpha05+, die LocusIdCompat und die neuen Kategorien für Training, Stoppuhr und Standortfreigabe enthält.

  • Wenn für deine App im Manifest mehr als eine MAIN LAUNCHER-Aktivität deklariert wurde, veröffentliche eine dynamische Verknüpfung und verknüpfe sie mithilfe von LocusId mit deiner laufenden Aktivität.

Medienbenachrichtigungen bei der Wiedergabe von Medien auf Wear OS-Geräten veröffentlichen

Wenn Medieninhalte auf einem Wear OS-Gerät wiedergegeben werden, veröffentliche eine Medienbenachrichtigung. So kann das System die entsprechende laufende Aktivität erstellen.

Wenn Sie Media3 verwenden, wird die Benachrichtigung automatisch veröffentlicht. Wenn Sie die Benachrichtigung manuell erstellen, sollte die MediaStyleNotificationHelper.MediaStyle verwendet werden und die entsprechende MediaSession sollte die Sitzungsaktivität enthalten.