DreamService w Androidzie: integracja z Jetpack Compose dla ekranów w trybie oczekiwania
DreamService, wprowadzony w Androidzie 4.2, pozwala wyświetlać niestandardowy UI na urządzeniu w trybie oczekiwania podczas ładowania. Komponent dziedziczy po Service i obsługuje elementy interaktywne, włączając przyciski. Do aktywacji wymagana jest ręczna konfiguracja przez użytkownika w ustawieniach wyświetlacza. To rozwiązanie nadaje się do tworzenia dynamicznych ekranów bez wpływu na główny lifecycle aplikacji.
Deklaracja usługi w AndroidManifest.xml jest standardowa:
<service
android:name=".MyDreamService"
android:exported="true"
android:description="@string/dream_service_description"
android:icon="@drawable/dream_service_icon"
android:label="@string/dream_service_label"
android:permission="android.permission.BIND_DREAM_SERVICE">
<intent-filter>
<action android:name="android.service.dreams.DreamService" />
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
</service>
Podstawowa implementacja wykorzystuje onAttachedToWindow() do konfiguracji widoku:
class MyDreamService : DreamService() {
override fun onAttachedToWindow() {
super.onAttachedToWindow()
isInteractive = false
isFullscreen = true
setContentView(R.layout.dream_service_layout)
}
}
Integracja Jetpack Compose z DreamService
Metoda setContentView działa tylko z View, dlatego dla Compose tworzy się ComposeView. Jednak DreamService nie udostępnia ViewTreeLifecycleOwner ani SavedStateRegistryOwner, co jest kluczowe dla poprawnego działania Compose.
Rozwiązaniem jest rozszerzenie DreamService z implementacją SavedStateRegistryOwner:
class MyDreamService : DreamService(), SavedStateRegistryOwner {
private val lifecycleRegistry = LifecycleRegistry(this)
private val savedStateRegistryController = SavedStateRegistryController.create(this)
override val lifecycle: Lifecycle
get() = lifecycleRegistry
override val savedStateRegistry: SavedStateRegistry
get() = savedStateRegistryController.savedStateRegistry
}
W onAttachedToWindow() zsynchronizuj lifecycle i registry:
val composeView = ComposeView(this).apply {
setViewTreeLifecycleOwner(this@MyDreamService)
setViewTreeSavedStateRegistryOwner(this@MyDreamService)
setContent {
DreamServiceTheme {
DreamScreen(
onOpenSettings = {
openSettingsAndExitDream()
}
)
}
}
}
setContentView(composeView)
Nie zapomnij wywoływać metod lifecycle w callbackach DreamService (onAttachedToWindow, onDetachedFromWindow itp.) dla prawidłowej synchronizacji stanów.
Kluczowe ograniczenia i najlepsze praktyki
- Aktywacja: Użytkownik musi ręcznie włączyć Daydream w ustawieniach. Automatyczne uruchomienie jest niemożliwe.
- Lifecycle: Zapewnij pełną implementację
LifecycleOwnerdla Compose, w przeciwnym razie UI nie zostanie zaktualizowane. - Wydajność: Unikaj ciężkich animacji — urządzenie jest w trybie uśpienia.
- Interaktywność:
isInteractive = truepozwala na przyciski, ale wymaga ostrożności względem zużycia energii.
Lista kroków wdrożenia:
- Zadeklaruj usługę w manifeście z uprawnieniem
BIND_DREAM_SERVICE. - Dziedzicz po
DreamServicei dodajSavedStateRegistryOwner. - Zainicjalizuj
LifecycleRegistryiSavedStateRegistryController. - W
ComposeViewustaw owners przedsetContent. - Testuj na rzeczywistym urządzeniu w trybie ładowania.
Co ważne
- DreamService to pełnoprawny host UI poza Activity, z obsługą Compose po dostosowaniu lifecycle.
- Wymagana jest ręczna aktywacja w ustawieniach wyświetlacza.
- Rozwiązanie problemów z
ViewTreeLifecycleOwnerpoprzez rozszerzenie usługi. - Nadaje się do ekranów oczekiwania: zegary, powiadomienia, mini-gry.
- Oszczędzanie energii jest kluczowe — minimalizuj wywołania rysowania.
Ta funkcja rozszerza możliwości rozwoju Androida, pozwalając customizować zachowanie urządzenia w niestandardowych scenariuszach. Dla senior developerów przydatna w kontekście głębokiego zrozumienia usług systemowych i ich integracji z nowoczesnymi frameworkami UI.
— Editorial Team
Brak komentarzy.