Always-on-Apps und Inaktivmodus des Systems

In diesem Leitfaden wird erläutert, wie Sie Ihre App so gestalten, dass sie immer aktiv ist, wie Sie auf Änderungen des Energiestatus reagieren und wie Sie das Verhalten der App so verwalten, dass sie Akkuleistung spart und gleichzeitig eine gute Nutzererfahrung bietet.

Wenn eine App ständig sichtbar ist, wird die Akkulaufzeit erheblich beeinträchtigt. Berücksichtigen Sie daher die Auswirkungen auf den Akku, wenn Sie diese Funktion hinzufügen.

Schlüsselkonzepte

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

  • Interaktiv: Ein Zustand mit hohem Stromverbrauch, in dem der Bildschirm die volle Helligkeit hat und Nutzerinteraktionen möglich sind.
  • Inaktiv: Ein Energiesparmodus, in dem das Display gedimmt wird, um Strom zu sparen. In diesem Zustand nimmt die Benutzeroberfläche Ihrer App weiterhin den gesamten Bildschirm ein, das System kann jedoch ihr Erscheinungsbild ändern, indem es sie unkenntlich macht oder Overlay-Inhalte wie die Uhrzeit anzeigt. Dies wird auch als Inaktivmodus bezeichnet.

Das Betriebssystem steuert den Übergang zwischen diesen Status.

Eine Always-On-App ist eine Anwendung, die Inhalte sowohl im interaktiven als auch im Inaktivitätsmodus anzeigt.

Wenn eine Always-on-App weiterhin ihre eigene Benutzeroberfläche anzeigt, während sich das Gerät im Energiesparmodus Ambient befindet, wird sie als ambiactive bezeichnet.

Systemübergänge und Standardverhalten

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

  • Zeitüberschreitung 1: Interaktiver Modus zum Inaktivmodus:Nach einer gewissen Zeit der Inaktivität des Nutzers wechselt das Gerät in den Inaktivmodus.
  • Zeitüberschreitung 2: Zum Zifferblatt zurückkehren:Nach einem weiteren Zeitraum der Inaktivität kann das System die aktuelle App ausblenden und das Zifferblatt anzeigen.

Unmittelbar nach dem ersten Übergang des Systems in den Status Ambient hängt das Standardverhalten von der Wear OS-Version und der Konfiguration Ihrer App ab:

  • Bei Wear OS 5 und niedriger zeigt das System einen verschwommenen Screenshot der pausierten App mit der darüber gelegten Uhrzeit an. Dieser Status wird im folgenden Flussdiagramm durch den Knoten „AOD Lite“ dargestellt.
  • Unter Wear OS 6 und höher gilt eine App als durchgehend aktiv, wenn sie auf SDK 36 oder höher ausgerichtet ist. Das Display wird gedimmt, die Anwendung wird aber weiterhin ausgeführt und bleibt sichtbar. (Updates können bis zu 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 auf allen Wear OS-Versionen das Erscheinungsbild oder Verhalten Ihrer App im Ambient-Status anpassen. Verwenden Sie dazu LocalAmbientModeManager, um Statusübergänge in Jetpack Compose unter Wear OS zu beobachten. Dieser Status wird im folgenden Flussdiagramm durch den Knoten „Ambiactive Mode“ dargestellt.

Status des Inaktivmodus beobachten

So reagieren Sie in Jetpack Compose unter Wear OS auf Ereignisse im Inaktivmodus:

  1. Verwende LocalAmbientModeManager, um Änderungen am Status des Ambient-Modus des Systems zu beobachten und deine Composables entsprechend anzupassen. Konfiguriere deine Komponente so, dass sie im Status AmbientMode.Ambient in einen Energiesparmodus wechselt und im Status AmbientMode.Interactive wieder vollständig interaktiv ist.

    // In a production application, the AmbientModeManager should be instantiated and provided at
    // the highest level of the Compose hierarchy (typically in the host Activity's setContent
    // block) using a CompositionLocalProvider. This ensures proper lifecycle management and
    // broad accessibility.
    
    // For this self-contained demo, AmbientModeManager is created and provided locally:
    val activityAmbientModeManager = rememberAmbientModeManager()
    CompositionLocalProvider(LocalAmbientModeManager provides activityAmbientModeManager) {
        val ambientModeManager = LocalAmbientModeManager.current
        val ambientMode = ambientModeManager?.currentAmbientMode
    
        if (ambientModeManager != null) {
            ambientModeManager.AmbientTickEffect {
                // While device is in ambient mode, update properties every minute or so
                // ...
            }
        }
    
        // ...
            val ambientModeName =
                when (ambientMode) {
                    is AmbientMode.Interactive -> "Interactive"
                    is AmbientMode.Ambient -> "Ambient"
                    else -> "Unknown"
                }
    
            Text(text = "$ambientModeName Mode")
            // ...
    }

Flussdiagramm für das Verhalten im Ambient-Modus

Das folgende Flussdiagramm zeigt, wie das System das Verhalten im Ambient-Modus basierend auf der Wear OS-Version des Geräts, dem targetSdkVersion deiner App und der Frage, ob Ambient-Statusübergänge beobachtet werden (mit LocalAmbientModeManager oder 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: Flussdiagramm zur Entscheidungslogik für den Wear OS-Inaktivmodus.

Dauer des eingeschalteten Displays festlegen

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

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

Nach einer bestimmten Zeit im Ambient-Zustand (Timeout 2) kehrt das System in der Regel zum Zifferblatt zurück. Der Nutzer kann die Zeitüberschreitungsdauer in den Systemeinstellungen konfigurieren. Bei bestimmten Anwendungsfällen, z. B. wenn ein Nutzer ein Training aufzeichnet, muss eine App möglicherweise länger sichtbar bleiben.

Bei Wear OS 5 und höher können Sie dies verhindern, indem Sie eine laufende Aktivität implementieren. Wenn in Ihrer App Informationen zu einer laufenden Nutzeraufgabe wie einem Training angezeigt werden, können Sie die Ongoing Activity API verwenden, um Ihre App bis zum Ende der Aufgabe sichtbar zu halten. Wenn ein Nutzer manuell zum Zifferblatt zurückkehrt, kann er über die Anzeige für laufende Aktivitäten mit nur einem Tippen zu deiner App zurückkehren.

Alternativ können Sie unter Wear OS 7 und höher anstelle einer laufenden Aktivität ein Live-Update verwenden. Unterstütze zur Abwärtskompatibilität weiterhin laufende Aktivitäten auf Geräten mit Wear OS 6 oder niedriger.

Dazu muss der Touch-Intent der laufenden Benachrichtigung auf Ihre Always-On-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()

Bildschirm eingeschaltet lassen und Inaktivmodus verhindern

In seltenen Fällen müssen Sie möglicherweise vollständig verhindern, dass das Gerät in den Inaktivmodus wechselt. Das heißt, um Timeout 1 zu vermeiden. Dazu können Sie den Modifikator keepScreenOn verwenden. Dies funktioniert wie ein Wakelock, der das Gerät im Zustand Interaktiv hält. Verwenden Sie diese Funktion mit äußerster Vorsicht, da sie die Akkulaufzeit erheblich beeinträchtigt.

Empfehlungen für den Inaktivmodus

Damit die Nutzerfreundlichkeit optimiert und der Akku im Ambient-Modus geschont wird, solltest du diese Designrichtlinien beachten. Bei diesen Empfehlungen wird eine klare Nutzererfahrung priorisiert, indem irreführende Informationen vermieden und visuelle Unordnung reduziert wird. Gleichzeitig wird die Anzeigefunktion optimiert.

  • Visuelles Durcheinander reduzieren und Energieverbrauch des Displays senken Eine übersichtliche, minimalistische Benutzeroberfläche signalisiert dem Nutzer, dass sich die App im Energiesparmodus befindet, und spart durch die Begrenzung heller Pixel deutlich Akku.
    • Mindestens 85% des Bildschirms müssen schwarz sein (das Verhältnis von On-Pixeln darf höchstens 15% betragen).
    • 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 Umrisslinien anstelle von Volltonfarben und passen Sie den Kontrast der Umrisslinien so an, dass die Elemente lesbar bleiben, ohne dass das Risiko von Bildschirmflimmern oder Einbrennen besteht.
    • Vermeiden Sie große Blöcke mit durchgehender Farbe sowie nicht funktionsfähige Branding- oder Hintergrundbilder.
  • Veraltete dynamische Daten und Animationen verarbeiten
    • Der AmbientTickEffect-Callback wird nur in regelmäßigen Abständen aufgerufen, in der Regel einmal pro Minute, um Strom zu sparen. Aufgrund dieser Einschränkung werden Daten, die sich häufig ändern, z. B. Stoppuhr, Herzfrequenz oder Trainingsdistanz, zwischen den Aktualisierungen veraltet. Um irreführende und falsche Informationen zu vermeiden, ersetzen Sie diese Live-Werte durch statische Platzhalterinhalte wie --.
    • Entfernen Sie Fortschrittsanzeigen, die häufige Aktualisierungen erfordern, um für den aktuellen Kontext oder die aktuelle Situation des Nutzers nützlich zu sein, z. B. Fortschrittsringe für kurze Mediensitzungen. Sie können Fortschrittsanzeigen beibehalten, wenn Aktualisierungen einmal pro Minute weiterhin sinnvoll sind, z. B. bei langen Timern.
    • Pausieren oder entfernen Sie alle Animationen im Inaktivmodus, einschließlich animierter Fortschrittsanzeigen und Lauftext.
  • Einheitliches Layout beibehalten
    • Elemente sollten in den Modi Interaktiv und Ambient an derselben Position bleiben, um einen reibungslosen Übergang zu ermöglichen. Interaktive UI-Elemente wie Schaltflächen können sichtbar bleiben, da moderne Wear OS-Geräte die Touch-Eingabe während Ambient-Sitzungen unterstützen.
    • Immer die aktuelle Uhrzeit anzeigen. In Jetpack Compose für Wear OS ist TimeText (standardmäßig in ScreenScaffold enthalten) an den Umgebungsmodus angepasst und wird im Umgebungsmodus einmal pro Minute automatisch aktualisiert.
  • Kontext berücksichtigen
    • Wenn sich der Nutzer auf einem Einstellungs- oder Konfigurationsbildschirm befand, als das Gerät in den Inaktivmodus wechselte, sollten Sie in Ihrer App einen relevanteren Bildschirm anstelle der Einstellungen anzeigen.
  • Gerätespezifische Anforderungen berücksichtigen
    • Wenn currentAmbientMode AmbientMode.Ambient zurückgibt:
      • Wenn isLowBitAmbientSupported gleich true ist, unterstützt das Display im Ambient-Modus weniger Bits pro Farbe. Deaktivieren Sie das Anti-Aliasing (z. B. bei benutzerdefinierten Canvas- oder Paint-Zeichnungsvorgängen) und vermeiden Sie nach Möglichkeit Farbverläufe.
      • Wenn isBurnInProtectionRequired den Wert true hat, verschiebt das System die angezeigten Inhalte regelmäßig, um ein Einbrennen von Pixeln zu verhindern. Verschieben Sie UI-Elemente in Ihrer App nicht manuell. Vermeiden Sie stattdessen rein weiße Bereiche und platzieren Sie wichtige UI-Elemente mindestens 10 Pixel vom Bildschirmrand entfernt, damit sie nicht abgeschnitten werden, wenn das System das Display verschiebt. (Standard-Wear Compose-Layouts wie ScreenScaffold bieten bereits ausreichend Randabstand.)

Debugging und Tests

Diese adb-Befehle können beim Entwickeln oder Testen des Verhaltens Ihrer App im Inaktivmodus hilfreich sein:

# 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 des gesamten Trainings Messwerte anzeigen muss. Die App muss bei Übergängen in den Ambient-Modus sichtbar bleiben und darf nicht durch das Zifferblatt ersetzt werden.

Dazu sollte der Entwickler Folgendes tun:

  1. Verwende LocalAmbientModeManager, um UI-Änderungen zwischen den Status Interactive und Ambient zu verarbeiten, z. B. das Dimmen des Displays und das Entfernen nicht benötigter Daten.
  2. Erstelle ein neues Layout mit geringem Stromverbrauch für den Ambient-Modus, das den Best Practices entspricht.
  3. Verwende während des Trainings die Ongoing Activity API (oder Live Updates unter Wear OS 7 und höher), damit das System nicht zum Zifferblatt zurückkehrt.

Eine vollständige Implementierung finden Sie im Compose-basierten Übungsbeispiel auf GitHub. In diesem Beispiel wird auch die Verwendung der zusammensetzbaren Funktion LocalAmbientModeManager veranschaulicht, um die Verarbeitung des Inaktivmodus in Compose zu vereinfachen.