Powrót do strony głównej

DreamService i Compose w Androidzie 4.2+

DreamService pozwala tworzyć UI w trybie uśpienia Androida podczas ładowania. Integracja Jetpack Compose wymaga implementacji LifecycleOwner i SavedStateRegistryOwner. Krok po kroku przewodnik z kodem dla middle/senior programistów.

Compose w DreamService: UI dla uśpionego Androida
Advertisement 728x90

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:

Google AdInline article slot
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:

Google AdInline article slot
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ę LifecycleOwner dla Compose, w przeciwnym razie UI nie zostanie zaktualizowane.
  • Wydajność: Unikaj ciężkich animacji — urządzenie jest w trybie uśpienia.
  • Interaktywność: isInteractive = true pozwala 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 DreamService i dodaj SavedStateRegistryOwner.
  • Zainicjalizuj LifecycleRegistry i SavedStateRegistryController.
  • W ComposeView ustaw owners przed setContent.
  • 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 ViewTreeLifecycleOwner poprzez 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.

Google AdInline article slot

— Editorial Team

Advertisement 728x90

Czytaj dalej