Always-on-Apps und Inaktivmodus des Systems

In diesem Leitfaden wird erläutert, wie Sie Ihre App immer aktiv halten, wie Sie auf Übergänge des Energiestatus reagieren und wie Sie das Verhalten der Anwendung verwalten, um eine gute Nutzererfahrung zu bieten und gleichzeitig den Akku zu schonen.

Wenn eine App ständig sichtbar ist, wirkt sich das erheblich auf die Akkulaufzeit aus. Berücksichtigen Sie daher die Auswirkungen auf den Energieverbrauch, wenn Sie diese Funktion hinzufügen.

Schlüsselkonzepte

Wenn eine Wear OS-App im Vollbildmodus angezeigt wird, befindet sie sich in einem von zwei Energiestatus:

  • Interaktiv: Ein Status mit hohem Energieverbrauch, bei dem der Bildschirm mit voller Helligkeit angezeigt wird, die vollständige Nutzerinteraktion möglich ist.
  • Inaktivmodus: Ein Status mit niedrigem Energieverbrauch, bei dem das Display gedimmt wird, um Energie zu sparen. In diesem Status nimmt die UI Ihrer App weiterhin den gesamten Bildschirm ein, aber das System kann ihr Aussehen ändern, indem es sie unscharf macht oder Inhalte wie die Uhrzeit überlagert. Dieser Status wird auch als Inaktivmodus bezeichnet.

Das Betriebssystem steuert den Übergang zwischen diesen Status.

Eine immer aktive App ist eine Anwendung, die Inhalte sowohl im Status Interaktiv als auch im Status Inaktivmodus anzeigt.

Wenn eine immer aktive App ihre eigene UI weiterhin anzeigt, während sich das Gerät im Inaktivmodus mit niedrigem Energieverbrauch befindet, wird sie als ambiactive mode bezeichnet.

Systemübergänge und Standardverhalten

Wenn sich eine App im Vordergrund befindet, verwaltet das System die Übergänge des Energiestatus basierend auf zwei Zeitlimits, die durch Nutzerinaktivität ausgelöst werden.

  • Zeitlimit 1: Übergang vom interaktiven Status zum Inaktivmodus:Nach einer bestimmten Zeit der Nutzerinaktivität wechselt das Gerät in den Inaktivmodus.
  • Zeitlimit 2: Rückkehr zum Zifferblatt:Nach einer weiteren Zeit der Inaktivität kann das System die aktuelle App ausblenden und das Zifferblatt anzeigen.

Unmittelbar nachdem das System den ersten Übergang in den Inaktivmodus durchlaufen hat, hängt das Standardverhalten von der Wear OS-Version und der Konfiguration Ihrer App ab:

  • Unter Wear OS 5 und niedriger zeigt das System einen unscharfen Screenshot Ihrer pausierten Anwendung an, wobei die Uhrzeit darüber eingeblendet wird. Dieser Status wird im folgenden Flussdiagramm durch den Knoten „AOD Lite“ dargestellt.
  • Unter Wear OS 6 und höher gilt eine App als immer aktiv, wenn sie auf SDK 36 oder höher ausgerichtet ist. Das Display wird gedimmt, aber die Anwendung wird weiter ausgeführt und bleibt sichtbar. Aktualisierungen können nur einmal pro Minute erfolgen. Dieser Status wird im folgenden Flussdiagramm durch den Knoten „Global AOD“ dargestellt.

Verhalten für den Inaktivmodus anpassen

Unabhängig vom Standardverhalten des Systems können Sie unter allen Wear OS-Versionen das Aussehen oder Verhalten Ihrer App im Inaktivmodus anpassen, indem Sie AmbientLifecycleObserver verwenden, um auf Callbacks bei Statusübergängen zu warten. Dieser Status wird im folgenden Flussdiagramm durch den Knoten „Ambiactive Mode“ in dargestellt.

AmbientLifecycleObserver verwenden

Verwenden Sie die AmbientLifecycleObserver-Klasse, um auf Ereignisse im Inaktivmodus zu reagieren:

  1. Implementieren Sie die AmbientLifecycleObserver.AmbientLifecycleCallback Schnittstelle. Verwenden Sie die Methode onEnterAmbient(), um die UI für den Status mit niedrigem Energieverbrauch anzupassen, und onExitAmbient(), um sie auf die vollständige interaktive Anzeige zurückzusetzen.

    val ambientCallback = object : AmbientLifecycleObserver.AmbientLifecycleCallback {
        override fun onEnterAmbient(ambientDetails: AmbientLifecycleObserver.AmbientDetails) {
            // ... Called when moving from interactive mode into ambient mode.
            // Adjust UI for low-power state: dim colors, hide non-essential elements.
        }
    
        override fun onExitAmbient() {
            // ... Called when leaving ambient mode, back into interactive mode.
            // Restore full UI.
        }
    
        override fun onUpdateAmbient() {
            // ... Called by the system periodically (typically once per minute)
            // to allow the app to update its display while in ambient mode.
        }
    }

  2. Erstellen Sie einen AmbientLifecycleObserver und registrieren Sie ihn mit dem Lebenszyklus Ihrer Aktivität oder Ihres zusammensetzbaren Elements.

    private val ambientObserver = AmbientLifecycleObserver(activity, ambientCallback)
    
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        lifecycle.addObserver(ambientObserver)
    
        // ...
    }

  3. Rufen Sie removeObserver() auf, um den Observer in onDestroy() zu entfernen.

    override fun onDestroy() {
        super.onDestroy()
        lifecycle.removeObserver(ambientObserver)
    
        // ...
    }

Für Entwickler, die Jetpack Compose verwenden, bietet die Horologist-Bibliothek ein hilfreiches Utility, das AmbientAware zusammensetzbare Element, das die Implementierung dieses Musters vereinfacht.

Ambient-aware TimeText

Als Ausnahme von der Anforderung eines benutzerdefinierten Observers ist das TimeText Widget unter Wear OS 6 ambient-aware. Es wird automatisch einmal pro Minute aktualisiert, wenn sich das Gerät im Inaktivmodus befindet, ohne dass zusätzlicher Code erforderlich ist.

Flussdiagramm für das Verhalten im Inaktivmodus

Das folgende Flussdiagramm veranschaulicht, wie das System das Verhalten im Inaktivmodus basierend auf der Wear OS-Version des Geräts, dem targetSdkVersion Ihrer App und der Implementierung von AmbientLifecycleCallback bestimmt.

Ein Flussdiagramm, das die Entscheidungslogik für den Wear OS-Umgebungsmodus veranschaulicht. Es wird gezeigt, wie die Betriebssystemversion des Geräts und die Konfiguration der App eines von drei Ergebnissen bestimmen: ein verschwommenes Overlay, Global AOD oder der von der App verwaltete Ambiactive-Modus.
Abbildung 1.: Ein Flussdiagramm, das die Entscheidungslogik für den Inaktivmodus von Wear OS veranschaulicht.

Anzeigedauer steuern

In den folgenden Abschnitten wird beschrieben, wie Sie verwalten, wie lange Ihre App auf dem Bildschirm angezeigt wird.

Verhindern, dass mit einer laufenden Aktivität oder einem Live-Update zum Zifferblatt zurückgekehrt wird

Nach einer bestimmten Zeit im Inaktivmodus (Zeitlimit 2) kehrt das System normalerweise zum Zifferblatt zurück. Der Nutzer kann die Zeitlimitdauer in den Systemeinstellungen konfigurieren. In bestimmten Anwendungsfällen, z. B. wenn ein Nutzer ein Training aufzeichnet, muss eine App möglicherweise länger sichtbar bleiben.

Unter Wear OS 5 und höher können Sie dies verhindern, indem Sie eine laufende Aktivität implementieren. Wenn Ihre App Informationen zu einer laufenden Nutzeraufgabe anzeigt, z. B. einer Trainingseinheit, können Sie mit der Ongoing Activity API dafür sorgen, dass Ihre App so lange sichtbar bleibt, bis die Aufgabe beendet ist. Wenn ein Nutzer manuell zum Zifferblatt zurückkehrt, kann er mit der Anzeige für laufende Aktivitäten mit einem einzigen Tippen zu Ihrer App zurückkehren.

Alternativ können Sie unter Wear OS 7 und höher anstelle einer laufenden Aktivität ein Live-Update verwenden. Aus Gründen der Abwärtskompatibilität sollten Sie die laufende Aktivität weiterhin auf Geräten mit Wear OS 6 oder niedriger unterstützen.

Dazu muss die Touch-Intent der laufenden Benachrichtigung auf Ihre immer aktive Aktivität verweisen, wie im folgenden Code-Snippet gezeigt:

val activityIntent =
    Intent(this, AlwaysOnActivity::class.java).apply {
        flags = Intent.FLAG_ACTIVITY_SINGLE_TOP
    }

val pendingIntent =
    PendingIntent.getActivity(
        this,
        0,
        activityIntent,
        PendingIntent.FLAG_UPDATE_CURRENT or PendingIntent.FLAG_IMMUTABLE,
    )

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

// ...

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

ongoingActivity.apply(applicationContext)

val notification = notificationBuilder.build()

Display aktiviert lassen und Inaktivmodus verhindern

In seltenen Fällen müssen Sie möglicherweise verhindern, dass das Gerät in den Inaktivmodus wechselt. Das heißt, Sie müssen Zeitlimit 1 vermeiden. Dazu können Sie das FLAG_KEEP_SCREEN_ON Fenster-Flag verwenden. Dies fungiert als Wakelock und hält das Gerät im interaktiven Zustand. Verwenden Sie diese Funktion mit äußerster Vorsicht, da sie sich erheblich auf die Akkulaufzeit auswirkt.

Empfehlungen für den Inaktivmodus

Um die bestmögliche Nutzererfahrung zu bieten und im Inaktivmodus Energie zu sparen, folgen Sie diesen Designrichtlinien. Bei diesen Empfehlungen wird eine klare Nutzererfahrung priorisiert, indem irreführende Informationen vermieden und visuelles Durcheinander reduziert werden, während gleichzeitig die Energie des Displays optimiert wird.

  • Visuelles Durcheinander und Energieverbrauch des Displays reduzieren. Eine übersichtliche, minimalistische UI signalisiert dem Nutzer, dass sich die App im Status mit niedrigem Energieverbrauch befindet, und spart erheblich Akku, indem die Anzahl der hellen Pixel begrenzt wird.
    • Mindestens 85% des Bildschirms sollten schwarz sein.
    • Zeigen Sie nur die wichtigsten Informationen an und verschieben Sie sekundäre Details auf das interaktive Display.
    • Verwenden Sie für große Symbole oder Schaltflächen Umrisse anstelle von durchgehenden Füllungen.
    • Vermeiden Sie große Blöcke mit durchgehender Farbe und nicht funktionale Branding- oder Hintergrundbilder.
  • Veraltete dynamische Daten verarbeiten
    • Der Callback onUpdateAmbient() wird nur in regelmäßigen Abständen aufgerufen, in der Regel einmal pro Minute, um Energie zu sparen. Aufgrund dieser Einschränkung werden alle Daten, die sich häufig ändern, z. B. eine Stoppuhr, die Herzfrequenz oder die Trainingsdistanz, zwischen den Aktualisierungen veraltet. Um irreführende und falsche Informationen zu vermeiden, warten Sie auf den Callback onEnterAmbient und ersetzen Sie diese Live-Werte durch statische Platzhalterinhalte wie --.
  • Einheitliches Layout beibehalten
    • Halten Sie die Elemente in den Modi Interaktiv und Inaktivmodus an derselben Position, um einen reibungslosen Übergang zu ermöglichen.
    • Zeigen Sie immer die Uhrzeit an.
  • Kontext berücksichtigen
    • Wenn sich der Nutzer auf einem Einstellungs- oder Konfigurationsbildschirm befand, als das Gerät in den Inaktivmodus wechselte, sollten Sie stattdessen einen relevanteren Bildschirm aus Ihrer App anzeigen.
  • Gerätespezifische Anforderungen berücksichtigen
    • Im AmbientDetails Objekt, das an onEnterAmbient() übergeben wird:
      • Wenn deviceHasLowBitAmbient true ist, deaktivieren Sie nach Möglichkeit das Antialiasing.
      • Wenn burnInProtectionRequired true ist, verschieben Sie die UI-Elemente regelmäßig leicht und vermeiden Sie durchgehende weiße Bereiche, um ein Einbrennen des Bildschirms zu verhindern.

Fehlerbehebung und Tests

Diese adb-Befehle können bei der Entwicklung oder beim Testen des Verhaltens Ihrer App nützlich sein, wenn sich das Gerät im Inaktivmodus befindet:

# put device in ambient mode if the always on display is enabled in settings
# (and not disabled by other settings, such as theatre mode)
$ adb shell input keyevent KEYCODE_SLEEP

# put device in interactive mode
$ adb shell input keyevent KEYCODE_WAKEUP

Beispiel: Trainings-App

Nehmen wir als Beispiel eine Trainings-App, die dem Nutzer während der gesamten Trainingseinheit Messwerte anzeigen muss. Die App muss während der Übergänge des Inaktivmodus sichtbar bleiben und darf nicht durch das Zifferblatt ersetzt werden.

Dazu sollte der Entwickler Folgendes tun:

  1. Implementieren Sie einen AmbientLifecycleObserver, um UI-Änderungen zwischen den Modi Interaktiv und Inaktivmodus zu verarbeiten, z. B. das Dimmen des Bildschirms und das Entfernen nicht benötigter Daten.
  2. Erstellen Sie ein neues Layout mit niedrigem Energieverbrauch für den Inaktivmodus, das den Best Practices entspricht.
  3. Verwenden Sie während des Trainings die Ongoing Activity API (oder Live Updates unter Wear OS 7 und höher), um zu verhindern, dass das System zum Zifferblatt zurückkehrt.

Eine vollständige Implementierung finden Sie im Compose-basierten Trainingsbeispiel auf GitHub. In diesem Beispiel wird auch die Verwendung des AmbientAware zusammensetzbaren Elements aus der Horologist-Bibliothek veranschaulicht, um die Verarbeitung des Inaktivmodus in Compose zu vereinfachen.