Z tego przewodnika dowiesz się, jak sprawić, aby aplikacja była zawsze włączona, jak reagować na zmiany stanu zasilania i jak zarządzać działaniem aplikacji, aby zapewnić użytkownikom komfort korzystania z niej przy jednoczesnym oszczędzaniu baterii.
Ciągłe wyświetlanie aplikacji ma znaczący wpływ na czas pracy baterii, więc podczas dodawania tej funkcji należy wziąć pod uwagę zużycie energii.
Kluczowe pojęcia
Gdy aplikacja na Wear OS jest wyświetlana na pełnym ekranie, może być w jednym z 2 stanów zasilania:
- Interaktywny: stan o wysokim poborze mocy, w którym ekran jest w pełni jasny i umożliwia pełną interakcję z użytkownikiem.
- Wygaszacz: stan niskiego zużycia energii, w którym wyświetlacz przyciemnia się, aby oszczędzać energię. W tym stanie interfejs aplikacji nadal zajmuje cały ekran, ale system może zmienić jego wygląd, np. rozmyć go lub wyświetlić nakładkę z treściami, takimi jak godzina. Jest to również tzw. oświetlenie kinowe.
System operacyjny kontroluje przejście między tymi stanami.
Aplikacja zawsze włączona to aplikacja, która wyświetla treści w trybach interaktywnym i otoczenia.
Gdy zawsze aktywna aplikacja nadal wyświetla swój interfejs, gdy urządzenie jest w stanie niskiego zużycia energii Ambient, mówimy, że jest w trybie ambiactive.
Przejścia systemowe i domyślne zachowanie
Gdy aplikacja działa na pierwszym planie, system zarządza przejściami między stanami zasilania na podstawie 2 limitów czasu wywoływanych przez nieaktywność użytkownika.
- Limit czasu 1: stan interaktywny do stanu otoczenia: po okresie nieaktywności użytkownika urządzenie przechodzi w stan otoczenia.
- Timeout 2. Powrót do tarczy zegarka: po kolejnym okresie braku aktywności system może ukryć bieżącą aplikację i wyświetlić tarczę zegarka.
Bezpośrednio po pierwszym przejściu systemu do stanu Ambient domyślne działanie zależy od wersji Wear OS i konfiguracji aplikacji:
- Na Wear OS 5 i starszych system wyświetla rozmyty zrzut ekranu wstrzymanej aplikacji z nałożonym na niego czasem. Ten stan jest reprezentowany przez węzeł „AOD Lite” na tym schemacie blokowym.
- Na Wear OS 6 i nowszych wersjach, jeśli aplikacja jest kierowana na pakiet SDK 36 lub nowszy, jest uznawana za zawsze włączoną. Wyświetlacz jest przyciemniony, ale aplikacja nadal działa i jest widoczna. (Aktualizacje mogą być wykonywane nawet raz na minutę). Ten stan jest reprezentowany przez węzeł „Global AOD” na tym schemacie blokowym.
Dostosowywanie działania w trybie nieaktywnym
Niezależnie od domyślnego działania systemu we wszystkich wersjach Wear OS możesz dostosować wygląd lub działanie aplikacji w stanie Ambient, używając LocalAmbientModeManager do obserwowania przejść między stanami w Jetpack Compose na Wear OS. Ten stan jest reprezentowany przez węzeł „Ambiactive Mode” w tym schemacie blokowym.
Obserwowanie stanu otoczenia
Aby reagować na zdarzenia w trybie nieaktywnym w Jetpack Compose na Wear OS:
Użyj
LocalAmbientModeManager, aby obserwować zmiany stanu trybu otoczenia systemu i odpowiednio dostosowywać elementy kompozycyjne. Skonfiguruj komponent tak, aby przełączał się w tryb niskiego zużycia energii w stanieAmbientMode.Ambienti wracał do pełnego interaktywnego wyświetlania w stanieAmbientMode.Interactive.// 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") // ... }
Deweloperzy korzystający z Jetpack Compose mogą używać LocalAmbientModeManager, co upraszcza implementację tego wzorca.
Schemat blokowy działania w trybie otoczenia
Poniższy schemat blokowy pokazuje, jak system określa zachowanie w trybie otoczenia na podstawie wersji Wear OS na urządzeniu, targetSdkVersion aplikacji i tego, czy implementuje ona AmbientLifecycleCallback.
Sterowanie czasem włączenia ekranu
W sekcjach poniżej znajdziesz informacje o tym, jak zarządzać czasem wyświetlania aplikacji na ekranie.
Zapobieganie powrotowi do tarczy zegarka z trwającą aktywnością lub aktualizacją na żywo
Po pewnym czasie w stanie Ambient (Timeout 2) system zwykle wraca do tarczy zegara. Użytkownik może skonfigurować czas trwania limitu czasu w ustawieniach systemu. W niektórych przypadkach, np. gdy użytkownik śledzi trening, aplikacja może potrzebować dłuższego czasu widoczności.
W przypadku Wear OS 5 i nowszych możesz temu zapobiec, wdrażając OngoingActivity. Jeśli aplikacja wyświetla informacje o trwającym zadaniu użytkownika, np. o sesji treningowej, możesz użyć interfejsu Ongoing Activity API, aby aplikacja była widoczna do czasu zakończenia zadania. Jeśli użytkownik ręcznie wróci do tarczy zegarka, wskaźnik trwającej aktywności umożliwi mu powrót do aplikacji jednym kliknięciem.
Na zegarkach z Wear OS 7 lub nowszym możesz też użyć aktualizacji na żywo zamiast trwającej aktywności. Aby zachować zgodność wsteczną, nadal obsługuj trwającą aktywność na urządzeniach z Wear OS 6 lub starszym.
Aby to zaimplementować, intencja dotknięcia trwałego powiadomienia musi wskazywać aktywność zawsze włączoną, jak pokazano w tym fragmencie kodu:
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()
Pozostawianie włączonego ekranu i zapobieganie przejściu w stan nieaktywny
W rzadkich przypadkach może być konieczne całkowite uniemożliwienie przejścia urządzenia w stan nieaktywny. Chodzi o uniknięcie przekroczenia limitu czasu nr 1. Możesz do tego użyć modyfikatora keepScreenOn. Działa to jak blokada uśpienia, która utrzymuje urządzenie w stanie interaktywnym. Używaj tej funkcji z dużą ostrożnością, ponieważ ma ona duży wpływ na czas pracy baterii.
Zalecenia dotyczące trybu nieaktywnego
Aby zapewnić użytkownikom jak najlepsze wrażenia i oszczędzać energię w trybie Ambient, postępuj zgodnie z tymi wytycznymi dotyczącymi projektowania. Te rekomendacje stawiają na pierwszym miejscu wygodę użytkowników, zapobiegając wprowadzaniu ich w błąd i ograniczając wizualny chaos, a jednocześnie optymalizując moc wyświetlania.
- Zmniejsz wizualny bałagan i zwiększ moc wyświetlania. Czysty, minimalistyczny interfejs informuje użytkownika, że aplikacja jest w stanie niskiego zużycia energii, i znacznie oszczędza baterię, ograniczając jasne piksele.
- Co najmniej 85% ekranu musi być czarne.
- Wyświetlaj tylko najważniejsze informacje, a szczegóły dodatkowe przenieś na wyświetlacz interaktywny.
- W przypadku dużych ikon lub przycisków używaj obramowań zamiast pełnych wypełnień.
- Unikaj dużych bloków jednolitego koloru oraz niefunkcjonalnych elementów marki lub obrazów tła.
- Obsługa nieaktualnych danych dynamicznych
- Wywołanie zwrotne
AmbientTickEffectjest wywoływane tylko okresowo – zwykle raz na minutę – aby oszczędzać energię. Z tego powodu wszelkie dane, które często się zmieniają, np. stoper, tętno czy dystans treningu, stają się nieaktualne między aktualizacjami. Aby uniknąć wyświetlania wprowadzających w błąd i nieprawidłowych informacji, zastąp te wartości na żywo statyczną treścią zastępczą, np.--.
- Wywołanie zwrotne
- Zachowaj spójny układ
- Zachowaj elementy w tej samej pozycji w trybach interaktywnym i otoczenia, aby zapewnić płynne przejście.
- Zawsze pokazuj czas.
- Uwzględniaj kontekst
- Jeśli w momencie przejścia urządzenia w tryb otoczenia użytkownik był na ekranie ustawień lub konfiguracji, rozważ wyświetlenie bardziej odpowiedniego ekranu z Twojej aplikacji zamiast widoku ustawień.
- Obsługa wymagań dotyczących konkretnych urządzeń
- W obiekcie
AmbientModezwróconym przezcurrentAmbientMode:- Jeśli
isLowBitAmbientSupportedma wartośćtrue, wyłącz wygładzanie, jeśli to możliwe. - Jeśli
isBurnInProtectionRequiredma wartośćtrue, okresowo przesuwaj nieznacznie elementy interfejsu i unikaj jednolitych białych obszarów, aby zapobiec wypaleniu ekranu.
- Jeśli
- W obiekcie
Debugowanie i testowanie
Te polecenia adb mogą być przydatne podczas programowania lub testowania działania aplikacji, gdy urządzenie jest w trybie otoczenia:
# 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
Przykład: aplikacja do treningu
Weźmy pod uwagę aplikację do ćwiczeń, która musi wyświetlać użytkownikowi dane przez cały czas trwania sesji treningowej. Aplikacja musi być widoczna podczas przejść między stanami otoczenia i nie może być zastępowana przez tarczę zegarka.
Aby to zrobić, deweloper powinien wykonać te czynności:
- Użyj
LocalAmbientModeManager, aby obsługiwać zmiany interfejsu między stanami interaktywnym i otoczenia, takie jak przyciemnianie ekranu i usuwanie nieistotnych danych. - Utwórz nowy układ o niskim poborze mocy dla stanu Ambient, który jest zgodny ze sprawdzonymi metodami.
- Używaj interfejsu Ongoing Activity API (lub Aktualizacji na żywo na Wear OS 7 i nowszych) przez cały czas trwania treningu, aby zapobiec powrotowi systemu do tarczy zegarka.
Pełną implementację znajdziesz w przykładowej aplikacji do ćwiczeń opartej na Compose w GitHubie. Ten przykład pokazuje też, jak używać funkcji kompozycyjnej LocalAmbientModeManager, aby uprościć obsługę trybu otoczenia w Compose.