Podstawy aplikacji

Przekształcanie kart w widżety na Wear za pomocą Jetpack Glance i Remote Compose

Głośniki

  • François Deschênes

    Menedżer produktu

  • Yuri Schimke

    Inżynier oprogramowania

Informacje

Informacje o wystąpieniu

Podczas tej sesji szczegółowo omówimy techniczne aspekty przejścia od pełnoekranowych kart do dynamicznych widżetów na Wear OS o częściowej wysokości.

Omówimy korzyści techniczne ujednoliconego interfejsu Jetpack Glance API i nowego silnika Remote Compose oraz szczegółowo wyjaśnimy, jak płynnie współdziałają z Modern Android Development.

Na koniec przedstawimy najnowsze wskazówki dotyczące UX i omówimy praktyczne strategie migracji, które pomogą Ci stworzyć interfejs nowej generacji, który można łatwo przeglądać.

Podsumowanie

  • Wear OS przekształca pełnoekranowe karty w widżety na Wear, które są tworzone za pomocą Jetpack Glance i obsługiwane przez Remote Compose.
  • Remote Compose korzysta z tego samego kompilatora i środowiska wykonawczego co interfejs Jetpack Compose, jednocześnie bezpiecznie oddzielając interfejs od procesu aplikacji.
  • Małe i duże rozmiary kontenerów są dostosowane do formatów siatki mobilnej, a interfejsy API Jetpack Glance Wear zachowują zgodność wsteczną aż do Wear 4.
  • Migracja istniejących kafelków do widżetów może wykorzystywać zalecaną strategię podwójnej usługi lub pojedynczą usługę zgodności.

Umiejętności

Zasoby

Gemini Notebook

Tematy

  • wear-os
  • wear-widgets
  • jetpack-glance
  • remote-compose
  • tiles-migration
  • jetpack-compose

Transkrypcja

Pobierz transkrypcję

Wprowadzenie

  • Cześć wszystkim.

  • Nazywam się Frank i kieruję zespołem, który zajmuje się funkcjami Wear OS umożliwiającymi szybkie sprawdzanie informacji.

  • Zegarki są niezbędnymi, całodziennymi towarzyszami użytkowników. Dzisiaj pokażemy, jak wykorzystać nowe widżety na Wear.

  • Przyjrzymy się dwóm sposobom dostarczania najważniejszych funkcji bezpośrednio na nadgarstek użytkowników. Wykorzystamy do tego najnowsze interfejsy API, które zostały zaprojektowane tak, aby tworzenie aplikacji na Wear OS było dla deweloperów aplikacji na Androida, takich jak Ty, znajome i intuicyjne.

  • Na scenie dołączy do mnie mój genialny kolega i sąsiad z biurka, Yuri, który dokładnie wyjaśni, jak to robimy.

  • Cześć, nazywam się Yuri Schimke.

  • Jestem inżynierem w zespole Wear OS i zajmuję się głównie interfejsami API Remote Compose.

  • Dzisiaj krótko przedstawię Remote Compose, a potem omówię proces migracji z kafelków na widżety na Wear.

  • Teraz oddaję głos Frankowi.

Przekształcanie kart w widżety na Wear

  • Świetnie.

  • Dziękuję, Yuri.

  • Oficjalnie wprowadzamy zegarki do ujednoliconego ekosystemu widżetów Androida, przekształcając pełnoekranowe kafelki w widżety na Wear.

  • A ponieważ te funkcje są teraz tworzone za pomocą Jetpack Glance, możesz zobaczyć, że jest to ta sama infrastruktura, która jest używana w przypadku widżetów mobilnych.

  • W przyszłości tworzenie aplikacji na Wear będzie jeszcze bardziej znajome.

Omówienie funkcji tworzenia wiadomości na innym urządzeniu

  • Aby umożliwić korzystanie z tych funkcji, rozwijamy stos UI – podstawowy stos UI.

  • Widżety na Wear są oparte na Remote Compose, nowej platformie Androida do zdalnego interfejsu użytkownika.

  • Oznacza to, że możesz wreszcie używać deklaratywnego interfejsu API ściśle powiązanego z Jetpack Compose do tworzenia funkcji poza aplikacją, takich jak widżety.

  • Remote Compose zapewnia nowoczesną grafikę i elastyczne układy widżetów, a jednocześnie dba o wydajność i oszczędność baterii.

  • Dzięki oddzieleniu interfejsu od procesu aplikacji widżety są bezpiecznie serializowane i łatwo renderowane na wielu urządzeniach z Androidem.

  • Oznacza to, że możesz udostępniać te bogate funkcje na niemal wszystkich obsługiwanych platformach zdalnych przy minimalnym wysiłku.

Rozmiary układów i zgodność wsteczna

  • Aby przejście z kart na widżety było jak najpłynniejsze, wprowadzamy 2 standardowe rozmiary kontenerów: mały i duży.

  • Są one zaprojektowane tak, aby były ściśle dopasowane do formatów widżetów opartych na siatce 2 x 1 i 2 x 2, które znasz już z tworzenia widżetów na urządzenia mobilne.

  • Począwszy od Wear 7, w przypadku niektórych producentów sprzętu widżety Wear będą teraz znajdować się w pionowo przewijanym zasobniku obok widżetów innych aplikacji.

  • Tak na przykład wyglądają widżety na Wear OS na zegarku Samsung Galaxy Watch.

  • Architektura platformy została zaprojektowana tak, aby obsługiwać panele przewijane pionowo, gdy producenci sprzętu zaczną stosować ten wzorzec w przyszłości.

  • Nie musisz się martwić, że pominiesz jakichś użytkowników.

  • Interfejsy Jetpack Glance Wear API zostały zaprojektowane tak, aby zapewniać zgodność wsteczną aż do Wear 4.

  • Na starszych urządzeniach, które obsługują poziomy zasobnik widżetów lub kart, system zajmie się tym za Ciebie.

  • Wystarczy, że w kodzie określisz, że chcesz obsługiwać tryb pełnoekranowy, a system pobierze duży widżet i wyświetli go jako tradycyjne kafelki na pełnym ekranie na tych urządzeniach.

  • Teraz Yuri omówi kod, aby pokazać, jak dokładnie przenieść istniejące kafelki do widżetów na Wear.

Strategie migracji istniejących kart

  • Dziękuję, Frank.

  • Jeśli tworzysz nowy widżet na Wear od podstaw, jest to proste.

  • Wystarczy zdefiniować GlanceWearWidgetService i utworzyć interfejs za pomocą Remote Compose.

  • Jeśli jednak Twoja aplikacja ma już kafelek w wersji produkcyjnej, musisz przenieść zarówno usługi, jak i interfejs oraz dane.

  • Aby ułatwić przejście na nową wersję, przygotowaliśmy ścieżki, które zapewnią dotychczasowym użytkownikom płynne korzystanie z usługi.

  • W przypadku usługi możesz wybrać jedną z 2 strategii: podwójną lub pojedynczą.

  • W przypadku podwójnej usługi, którą zalecamy, zachowasz dotychczasową usługę TileService na starszych urządzeniach z Wear OS i dodasz nową usługę GlanceWearWidgetService na Wear OS 7 lub nowszym.

  • W przypadku pojedynczej usługi tworzysz nową, pojedynczą usługę GlanceWearWidgetService, która obsługuje oba protokoły i działa w trybie zgodności, aby przekształcić widżet w kartę na starszych urządzeniach.

  • W obu przypadkach nadal będziesz docierać do użytkowników.

  • Wpływa tylko na to, jaki kod będziesz utrzymywać w przyszłości.

  • Właśnie opublikowaliśmy na stronie dla deweloperów aplikacji na Androida obszerną dokumentację, w której szczegółowo opisujemy, jak i kiedy używać obu tych wzorców.

  • Zapoznaj się z nim, aby dowiedzieć się, która strategia będzie najlepsza w przypadku Twojej aplikacji.

Tworzenie interfejsu za pomocą Remote Compose

  • Porozmawiajmy teraz o warstwie interfejsu.

  • Podczas migracji zmienia się model mentalny.

  • Wcześniej karty korzystały z ProtoLayout, biblioteki utworzonej wyłącznie na potrzeby kart na Wear.

  • Z kolei widżety na Wear OS są oparte na funkcji Remote Compose.

  • Remote Compose korzysta z tej samej bazy co interfejs Jetpack Compose, używając tego samego podstawowego kompilatora i środowiska wykonawczego.

  • Został zaprojektowany tak, aby był znajomy i ściśle dopasowany do bibliotek interfejsu Compose, takich jak Foundation i Material 3.

  • Zamiast pola, kolumny lub tekstu użyjesz po prostu RemoteBox, RemoteColumn lub RemoteText.

  • W tym przypadku często będziesz pisać „remote”.

  • Aby przyspieszyć pracę, dodaliśmy pełny zestaw gotowych do użycia komponentów Remote Compose zaprojektowanych specjalnie pod kątem widżetów.

  • Oznacza to, że dotychczasowe projekty Wear Material 3, w tym te z Figmy, można łatwo dostosować do widżetów, co ułatwia pracę zarówno inżynierom, jak i projektantom.

  • Aby zobaczyć, jak bardzo te modele są ze sobą zgodne, przyjrzyjmy się konkretnemu przykładowi.

  • Utworzymy własny komponent aplikacji na podstawie przycisku przełącznika Material 3.

  • Po lewej stronie mamy standardowy komponent Wear Compose, który można napisać w aplikacji, a po prawej – wersję Remote Compose.

    // Wear Compose
    @Composable
    fun HistoryEraserButton(
      onClick: () -> Unit,
      modifier: Modifier = Modifier,
      checked: Boolean = true,
      onCheckedChange: (Boolean) -> Unit = {},
    )
    // Wear RemoteCompose
    @RemoteComposable
    @Composable
    fun RemoteHistoryEraserButton(
      onClick: Action,
      modifier: RemoteModifier = RemoteModifier,
      checked: RemoteBoolean = true.rb,
      onCheckedChange: Action = Action.Empty,
    )
  • Zwróć uwagę, jak podobne są te wzorce.

  • Jednak podczas pisania kodu Remote Compose użyjesz adnotacji RemoteComposable.

  • Jeśli używasz znanych parametrów, takich jak modyfikator i wartość logiczna, mają one odpowiedniki w Remote Compose, takie jak RemoteModifier i RemoteBoolean.

  • Zamiast funkcji lambda używasz działań.

  • Zamiast definiować kod do wykonania w funkcji lambda, musisz zadeklarować działanie, takie jak uruchomienie intencji oczekującej, wywołanie usługi lub zaktualizowanie wartości.

  • Przejdźmy do treści komponentu.

  • Zauważysz, że nawet motyw jest dopasowany.

  • Schemat kolorów Material 3 możesz zastosować do komponentu Remote Compose dokładnie tak samo jak w standardowym Compose, dzięki czemu widżet będzie dokładnie pasował do marki aplikacji.

    // Wear Compose
      val colors = MaterialTheme.colorScheme
      SplitSwitchButton(
        checked = checked,
        onCheckedChange = onCheckedChange,
        toggleContentDescription = "Arm Eraser",
        onContainerClick = onClick,
        modifier = modifier.fillMaxWidth(),
        colors =
          SwitchButtonDefaults.splitSwitchButtonColors(
            checkedContainerColor = colors.errorContainer, …
          ),
        label = { Text("History Eraser") },
        secondaryLabel = { Text("Don't touch it!") },
      )
    // Wear RemoteCompose
      val colors = RemoteMaterialTheme.colorScheme
      RemoteSplitSwitchButton(
        checked = checked,
        onCheckedChange = onCheckedChange,
        toggleContentDescription = "Arm Eraser".rs,
        onContainerClick = onClick,
        modifier = modifier.fillMaxWidth(),
        colors =
          RemoteSplitSwitchButtonDefaults.splitSwitchButtonColors(
            checkedContainerColor = colors.errorContainer, …
          ),
        label = { RemoteText("History Eraser".rs) },
        secondaryLabel = { RemoteText("Don't touch it!".rs) },
      )
  • Na koniec zobaczmy wynik. W rezultacie otrzymujemy dokładnie to, czego oczekujemy: przejrzysty, elastyczny i animowany przycisk przełączania.

Obsługa podglądu w widoku tworzenia w przypadku widżetów

  • Trudno jest odróżnić te 2 rodzaje.

  • Aby ułatwić projektowanie, iterowanie i weryfikowanie układów widżetów bez konieczności ciągłego uruchamiania ich na urządzeniu lub emulatorze, dodaliśmy obsługę podglądu Compose w przypadku widżetów na Wear.

  • Widżety zależą od ograniczeń kontenera specyficznych dla OEM, takich jak rozmiar, kształt, dopełnienie i promień narożnika, dlatego korzystamy ze standardowej adnotacji podglądu, ale z dodatkowym dostawcą parametrów, który umożliwia wstrzykiwanie tych konfiguracji.

    @Preview(name = "Squircle Preview", device = "spec:width=1000dp,height=1000dp,dpi=320")
    @Composable
    fun WeatherWidgetSquirclePreview(
        @PreviewParameter(SquircleAllWidgetPreviewParams::class) params: WearWidgetParams
    ) = WearWidgetPreview(MockWeatherWidget(65, WeatherCondition.CLOUDY), params)
    
    @Preview(name = "Round Preview", device = "spec:width=1000dp,height=1000dp,dpi=320")
    @Composable
    fun WeatherWidgetRoundPreview(
        @PreviewParameter(RoundAllWidgetPreviewParams::class) params: WearWidgetParams
    ) = WearWidgetPreview(MockWeatherWidget(65, WeatherCondition.CLOUDY), params)
  • Biblioteka zawiera wstępnie skonfigurowane implementacje dostawcy PreviewParameter, które odpowiadają rzeczywistym urządzeniom z Wear OS.

  • Te adnotacje podglądu umożliwiają łatwe sprawdzanie układu na różnych urządzeniach.

  • Oprócz testowania układów możesz używać tych podglądów do generowania obrazów statycznych wymaganych przez selektor widżetów na urządzeniu.

    @Preview(name = "Widget Picker Preview", device = "spec:width=1000dp,height=1000dp,dpi=320")
    @Composable
    fun WeatherWidgetRectangularPreview(
        @PreviewParameter(RectangularAllWidgetPreviewParams::class) params: WearWidgetParams
    ) = WearWidgetPreview(MockWeatherWidget(65, WeatherCondition.CLOUDY), params)
  • Biblioteka udostępnia parametr prostokątnego kształtu podglądu, który emuluje pełne, nieprzycięte prostokątne kontenery.

Przykładowe narzędzia do implementacji i migracji

  • Jeśli chcesz zobaczyć, jak to działa w praktyce, odświeżyliśmy naszą przykładową aplikację multimedialną Horologist, aby zawierała nowy widżet, który prezentuje ten interfejs API.

  • Pokazujemy, jak dodać małą i dużą wersję widżetu multimediów.

  • Sprawdź go na GitHubie, aby zobaczyć porównanie starszego kodu ProtoLayout i nowej implementacji Remote Compose.

  • Na pewno Ci się spodoba.

  • Na koniec nie byłoby to, no wiecie, wystąpienie, gdybym nie wspomniał o AI.

  • Aby przyspieszyć migrację, opublikowaliśmy na GitHubie nową umiejętność migracji kafelków do widżetów.

  • Możesz go używać z wybranym agentem lub dodać bezpośrednio do Android Studio za pomocą interfejsu wiersza poleceń Androida.

    android skills add wear-widgets
    android skills add --all
  • Teraz oddaję głos François, który podsumuje nasze spotkanie.

Podsumowanie i zakończenie

  • Dziękujemy.

  • Dziękuję, Yuri.

  • Jak widać, przekształcanie kart w widżety na Wear OS jest bardzo prostym procesem.

  • Podsumowując, przechodząc na Jetpack Glance Wear i Remote Compose, nie tylko aktualizujesz interfejs, ale też dołączasz do bardziej ujednoliconego ekosystemu widżetów na Androida.

  • Możesz teraz tworzyć atrakcyjne, zgodne wstecznie widżety, korzystając z nowoczesnego, deklaratywnego frameworka, który jest w pełni zgodny z Jetpack Compose.

  • Możesz zacząć przenosić kafelki już dziś. Aby dowiedzieć się więcej, zapoznaj się z przewodnikiem dla początkujących na stronie dla deweloperów aplikacji na Androida.

  • Z niecierpliwością czekamy na wszystkie ekspresyjne, łatwe do odczytania treści, które stworzysz na zegarki.

  • Dziękuję za udział w dzisiejszej sesji. Życzę udanej konferencji.

  • Dziękujemy.

Kod

Fragmenty kodu

Fragment kodu w języku Kotlin w 06:40 w filmie „Tworzenie interfejsu za pomocą Remote Compose”
// Wear Compose
@Composable
fun HistoryEraserButton(
  onClick: () -> Unit,
  modifier: Modifier = Modifier,
  checked: Boolean = true,
  onCheckedChange: (Boolean) -> Unit = {},
)
Fragment kodu w języku Kotlin w 06:40 w filmie „Tworzenie interfejsu za pomocą Remote Compose”
// Wear RemoteCompose
@RemoteComposable
@Composable
fun RemoteHistoryEraserButton(
  onClick: Action,
  modifier: RemoteModifier = RemoteModifier,
  checked: RemoteBoolean = true.rb,
  onCheckedChange: Action = Action.Empty,
)
Fragment kodu w języku Kotlin w 07:39 w filmie „Tworzenie interfejsu za pomocą Remote Compose”
// Wear Compose
  val colors = MaterialTheme.colorScheme
  SplitSwitchButton(
    checked = checked,
    onCheckedChange = onCheckedChange,
    toggleContentDescription = "Arm Eraser",
    onContainerClick = onClick,
    modifier = modifier.fillMaxWidth(),
    colors =
      SwitchButtonDefaults.splitSwitchButtonColors(
        checkedContainerColor = colors.errorContainer, …
      ),
    label = { Text("History Eraser") },
    secondaryLabel = { Text("Don't touch it!") },
  )
Fragment kodu w języku Kotlin w 07:39 w filmie „Tworzenie interfejsu za pomocą Remote Compose”
// Wear RemoteCompose
  val colors = RemoteMaterialTheme.colorScheme
  RemoteSplitSwitchButton(
    checked = checked,
    onCheckedChange = onCheckedChange,
    toggleContentDescription = "Arm Eraser".rs,
    onContainerClick = onClick,
    modifier = modifier.fillMaxWidth(),
    colors =
      RemoteSplitSwitchButtonDefaults.splitSwitchButtonColors(
        checkedContainerColor = colors.errorContainer, …
      ),
    label = { RemoteText("History Eraser".rs) },
    secondaryLabel = { RemoteText("Don't touch it!".rs) },
  )
Fragment kodu w Kotlinie w 08:20 w filmie „Compose preview support for widgets”
@Preview(name = "Squircle Preview", device = "spec:width=1000dp,height=1000dp,dpi=320")
@Composable
fun WeatherWidgetSquirclePreview(
    @PreviewParameter(SquircleAllWidgetPreviewParams::class) params: WearWidgetParams
) = WearWidgetPreview(MockWeatherWidget(65, WeatherCondition.CLOUDY), params)

@Preview(name = "Round Preview", device = "spec:width=1000dp,height=1000dp,dpi=320")
@Composable
fun WeatherWidgetRoundPreview(
    @PreviewParameter(RoundAllWidgetPreviewParams::class) params: WearWidgetParams
) = WearWidgetPreview(MockWeatherWidget(65, WeatherCondition.CLOUDY), params)
Fragment kodu w języku Kotlin w 08:58 w filmie „Obsługa podglądu widżetów w Compose”
@Preview(name = "Widget Picker Preview", device = "spec:width=1000dp,height=1000dp,dpi=320")
@Composable
fun WeatherWidgetRectangularPreview(
    @PreviewParameter(RectangularAllWidgetPreviewParams::class) params: WearWidgetParams
) = WearWidgetPreview(MockWeatherWidget(65, WeatherCondition.CLOUDY), params)
Fragment kodu powłoki w 09:58 w filmie „Przykładowa implementacja i narzędzia do migracji”
android skills add wear-widgets
android skills add --all