Laufende Aktivität

Wenn Sie in Wear OS eine laufende Aktivität mit einer laufenden Benachrichtigung koppeln, wird diese Benachrichtigung weiteren Oberflächen auf der Wear OS-Benutzeroberfläche hinzugefügt. So bleiben die Nutzer bei länger andauernden Aktivitäten interessierter.

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

Beispielsweise könnte ein Wear OS-Nutzer eine Trainings-App verwenden, um einen Lauf einer Aktivität aufzuzeichnen, und dann diese App verlassen, um eine andere Aufgabe zu starten. Wenn der Nutzer die Trainings-App verlässt, wechselt die App zu einer laufenden Benachrichtigung, die mit einigen Hintergrundarbeiten verbunden ist, um den Nutzer über seinen Lauf auf dem Laufenden zu halten. Die Benachrichtigung enthält Aktualisierungen des Nutzers und eine einfache Möglichkeit, die App wieder zu öffnen.

Um die Benachrichtigung anzusehen, müssen Nutzer jedoch in die Benachrichtigungsleiste unter dem Zifferblatt wischen, um die richtige Benachrichtigung zu finden. Dies ist nicht so praktisch wie auf anderen Oberflächen.

Mit der Ongoing Activity API kann die laufende Benachrichtigung einer App Informationen an mehrere neue, praktische Oberflächen unter Wear OS zur Verfügung stellen, damit der Nutzer interessiert bleibt.

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

Laufsymbol

Abbildung 1: Aktivitätsanzeige.

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

launcher

Abbildung 2: Global Launcher

In den folgenden Situationen empfiehlt es sich, eine fortlaufende Benachrichtigung zu verwenden, die mit einer laufenden Aktivität verbunden ist:

timer

Abbildung 3: Timer: Der Countdown läuft und endet, wenn der Timer pausiert oder gestoppt wird.

Karte

Abbildung 4: Schritt-für-Schritt-Navigation:Eine Wegbeschreibung zu einem Ziel wird angesagt. Sie endet, wenn der Nutzer das Ziel erreicht oder die Navigation beendet.

Musik

Abbildung 5: Medien:Zum Abspielen von Musik während einer Sitzung. Er endet unmittelbar, nachdem der Nutzer die Sitzung pausiert hat.

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

Im Codelab zu laufenden Aktivitäten finden Sie ein ausführliches Beispiel zum Erstellen laufender Aktivitäten für andere Arten von Apps.

Einrichten

Damit Sie die Ongoing Activity API in Ihrer App verwenden können, fügen Sie der Datei build.gradle der 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

Erstelle zuerst eine laufende Benachrichtigung und dann eine laufende Aktivität.

Laufende Benachrichtigung erstellen

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

Du musst eine laufende Aktivität mit einer laufenden Benachrichtigung koppeln. Die Verknüpfung Ihrer laufenden Aktivität mit einer Benachrichtigung bietet viele Vorteile:

  • Auf Geräten, die keine laufenden Aktivitäten unterstützen, sind Benachrichtigungen die Ausweichlösung. Die Benachrichtigung ist die einzige Oberfläche, die während der Ausführung Ihrer App im Hintergrund angezeigt wird.
  • Unter Android 11 und höher blendet Wear OS die Benachrichtigung in der Benachrichtigungsleiste aus, wenn die App als laufende Aktivität auf weiteren 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

Sobald Sie eine laufende Benachrichtigung erhalten, erstellen Sie eine laufende Aktivität, wie im folgenden Beispiel gezeigt. Lesen Sie sich die Kommentare durch, um sich ein Bild vom Verhalten der einzelnen Properties zu machen.

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

In den folgenden Schritten wird der wichtigste Teil des vorherigen Beispiels erläutert:

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

  2. Erstellen Sie für den Text ein OngoingActivityStatus oder eine andere Statusoption, wie im folgenden Abschnitt beschrieben.

  3. Erstellen Sie ein OngoingActivity und legen Sie eine Benachrichtigungs-ID fest.

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

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

Status

Mit Status kannst du dem Nutzer den aktuellen Live-Status von OngoingActivity auf neuen Oberflächen wie dem Bereich Zuletzt verwendet im Launcher 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 (Letzte) des App Launchers angezeigt werden soll.

Anschließend können Sie mit der Methode addTemplate() anpassen, wie Text bei Spans angezeigt wird. Dabei können Sie alle dynamischen Teile des Textes als Status.Part angeben.

Das folgende Beispiel zeigt, wie das Wort „time“ (Zeit) rot angezeigt wird. Im Beispiel wird ein Status.StopwatchPart verwendet, um eine Stoppuhr im Bereich Recents des App Launchers 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();

Um auf einen Teil aus der Vorlage zu verweisen, verwenden Sie den Namen umgeben von #. 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 wird. Dies ist einfacher als das manuelle Definieren eines Spannable-Objekts.

Weitere Anpassungen

Neben Status kannst du deine laufenden Aktivitäten und Benachrichtigungen so anpassen. Diese Anpassungen werden je nach Implementierung des OEMs 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:Steuerung des Medientransports für die Wiedergabe
    • CATEGORY_ALARM:Wecker oder Timer
    • CATEGORY_WORKOUT: ein Training (neue Kategorie)
    • CATEGORY_LOCATION_SHARING:Vorübergehende Standortfreigabe (neue Kategorie)
    • CATEGORY_STOPWATCH: Stoppuhr (neue Kategorie)

Laufende Aktivität

  • Animiertes Symbol:Ein schwarz-weißer Vektor, vorzugsweise mit transparentem Hintergrund. Wird im Aktivmodus auf dem Zifferblatt angezeigt. Ist kein animiertes Symbol vorhanden, wird das Standardbenachrichtigungssymbol verwendet. Das Standardbenachrichtigungssymbol ist je nach Anwendung unterschiedlich.

  • Statisches Symbol:Ein Vektorsymbol mit transparentem Hintergrund. Wird im Inaktivmodus auf dem Zifferblatt angezeigt. Wenn das animierte Symbol nicht festgelegt ist, wird das statische Symbol im Aktivmodus auf dem Zifferblatt verwendet. Andernfalls wird das Benachrichtigungssymbol verwendet. Wenn beides nicht festgelegt ist, wird eine Ausnahme ausgelöst. (Der App Launcher verwendet weiterhin das App-Symbol.)

  • OngoingActivityStatus:Nur Text oder Chronometer. Wird im App Launcher im Bereich Zuletzt verwendet angezeigt. Wenn nicht angegeben, wird der Kontexttext der Benachrichtigung verwendet.

  • Touch Intent:PendingIntent, mit dem wieder 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. Falls nicht angegeben, wird der inhaltsbezogene Intent verwendet. Wenn beides nicht festgelegt ist, wird eine Ausnahme ausgelöst.

  • LocusId: Die ID, mit der die Launcher-Verknüpfung zugewiesen wird, der die laufende Aktivität entspricht. Wird während der laufenden Aktivität im Launcher im Bereich Letzte angezeigt. Wenn nicht angegeben, blendet der Launcher alle App-Elemente im Abschnitt Recents (Letzte) aus demselben Paket aus und zeigt nur die laufende Aktivität an.

  • ID der laufenden Aktivität:Mit dieser ID lassen sich Aufrufe von fromExistingOngoingActivity() voneinander unterscheiden, wenn eine Anwendung mehr als eine laufende Aktivität hat.

Laufende Aktivität aktualisieren

In den meisten Fällen erstellen Entwickler eine neue laufende 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 einer OngoingActivity, wenn Sie eine Instanz beibehalten möchten, anstatt sie neu zu erstellen.

Wenn die App im Hintergrund ausgeführt wird, können Aktualisierungen an die Ongoing Activity API gesendet werden. Sie sollten dies jedoch nicht zu häufig tun, da die Aktualisierungsmethode Aufrufe ignoriert, die zu nah beieinander liegen. Einige wenige Aktualisierungen pro Minute sind in Ordnung.

Verwenden Sie zum Aktualisieren der laufenden Aktivität und der geposteten Benachrichtigung das Objekt, das Sie zuvor erstellt haben, 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, um eine laufende Aktivität zu erstellen.

Kotlin

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

Java

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

Laufende Aktivität beenden

Wenn die Anwendung als laufende Aktivität beendet ist, muss sie nur die laufende Benachrichtigung abbrechen.

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

Laufende Aktivität pausieren

Wenn Ihre App eine explizite Stoppaktion hat, fahren Sie nach dem Aufheben der Pausierung mit der laufenden Aktivität fort. Bei einer App ohne explizite Stoppaktion wird die Aktivität nach dem Anhalten beendet.

Best Practices

Beachten Sie bei der Arbeit mit der Ongoing Activity API Folgendes:

  • Ruf zuerst ongoingActivity.apply(context) an, bevor du notificationManager.notify(...) anrufst.
  • Legen Sie ein statisches Symbol für Ihre 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 ein Touch-Intent für deine laufende Aktivität fest, entweder explizit oder als Fallback über die Benachrichtigung. Andernfalls erhalten Sie ein IllegalArgumentException.

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

  • Wenn für Ihre App mehr als eine MAIN LAUNCHER-Aktivität im Manifest deklariert ist, veröffentlichen Sie ein dynamisches Kürzel und verknüpfen Sie es mithilfe von LocusId mit Ihrer 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öffentlichen Sie 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 MediaStyleNotificationHelper.MediaStyle verwendet werden. Für die entsprechende MediaSession sollte die Sitzungsaktivität eingetragen sein.