# Evolving Tiles to Wear Widgets using Jetpack Glance and Remote Compose - Speakers: François Deschênes (Product Manager), Yuri Schimke (Software Engineer) - Track: Apps foundation - Video: https://www.youtube.com/watch?v=5--1viVciq4 - Page: https://developer.android.com/events/dev-summit/talks/evolving-tiles-to-wear-widgets-using-jetpack-glance-and-remote-compose ## About the talk In this session, we will take a technical deep dive into the evolution from full-screen Tiles to dynamic, partial-height Wear Widgets. We will explore the technical benefits of the unified Jetpack Glance API and the new Remote Compose engine, detailing how they seamlessly align with Modern Android Development. Finally, we will share the latest UX guidance and walk through practical migration strategies to help you build the next generation of glanceable UI. ## Summary - Wear OS is evolving full-screen Tiles into Wear Widgets built with Jetpack Glance and powered by Remote Compose. - Remote Compose shares the same compiler and runtime as Jetpack Compose UI while safely decoupling your UI from the app process. - Small and large container sizes align with mobile grid formats, while Jetpack Glance Wear APIs maintain backward compatibility down to Wear 4. - Migrating existing Tiles to widgets can use either a recommended dual-service strategy or a single compatibility service. ## Skills - [Tiles to widgets migration skill](https://goo.gle/skills-repo) ## Resources - [Tile to widget service migration](https://goo.gle/wearos-tiles-widgets-migration) - [Horologist media sample app](https://goo.gle/media-sample) - [Wear Widgets getting started guide](https://goo.gle/wear-widgets) ## Topics wear-os, wear-widgets, jetpack-glance, remote-compose, tiles-migration, jetpack-compose ## Transcript ### Introduction [00:06](https://www.youtube.com/watch?v=5--1viVciq4&t=6s) Hey, everyone. [00:06](https://www.youtube.com/watch?v=5--1viVciq4&t=6s) My name is Frank, and I lead our glanceable experiences for Wear OS. [00:10](https://www.youtube.com/watch?v=5--1viVciq4&t=10s) Watches are essential, all-day companions to your users, and today, we'll walk you through how to leverage the new Wear Widgets experience. [00:19](https://www.youtube.com/watch?v=5--1viVciq4&t=19s) We'll look at two we'll look into delivering your most critical features directly to your users' wrist, and we'll do so using the latest APIs, APIs that are designed to make building for Wear OS feel familiar and intuitive to Android developers, such as yourself. [00:35](https://www.youtube.com/watch?v=5--1viVciq4&t=35s) Joining me on stage today to look into exactly how we're doing this is my brilliant colleague and desk buddy Yuri. [00:43](https://www.youtube.com/watch?v=5--1viVciq4&t=43s) Hi, I'm Yuri Schimke. [00:45](https://www.youtube.com/watch?v=5--1viVciq4&t=45s) I'm an engineer on the Wear OS team, and my main focus is working on the Remote Compose APIs. [00:52](https://www.youtube.com/watch?v=5--1viVciq4&t=52s) I'll give you a quick intro today to Remote Compose and then also talk about the process for migrating from Tiles to Wear Widgets. [01:00](https://www.youtube.com/watch?v=5--1viVciq4&t=60s) With that, I'll hand you back to Frank. ### Evolving Tiles to Wear Widgets [01:01](https://www.youtube.com/watch?v=5--1viVciq4&t=61s) Awesome. [01:03](https://www.youtube.com/watch?v=5--1viVciq4&t=63s) Thank you, Yuri. [01:04](https://www.youtube.com/watch?v=5--1viVciq4&t=64s) We're officially bringing the wrist into the unified Android widgets ecosystem by evolving our full-screen Tiles into Wear Widgets. [01:16](https://www.youtube.com/watch?v=5--1viVciq4&t=76s) And because these experiences are now built using Jetpack Glance, you can see that it's the same underlying infrastructure that is used for mobile widgets. [01:28](https://www.youtube.com/watch?v=5--1viVciq4&t=88s) You'll see that building for Wear is getting even more familiar for you in the future. ### Overview of Remote Compose [01:34](https://www.youtube.com/watch?v=5--1viVciq4&t=94s) To power these experiences, we are evolving the UI stack-- the underlying UI stack. [01:40](https://www.youtube.com/watch?v=5--1viVciq4&t=100s) Wear Widgets are powered by Remote Compose, a new Android framework for remote UI. [01:47](https://www.youtube.com/watch?v=5--1viVciq4&t=107s) This means you can finally use a declarative API closely aligned with Jetpack Compose to build your out-of-app experiences, such as widgets. [01:56](https://www.youtube.com/watch?v=5--1viVciq4&t=116s) Remote Compose brings modern graphics and responsive layouts to widgets while ensuring performance and battery efficiency. [02:05](https://www.youtube.com/watch?v=5--1viVciq4&t=125s) And by decoupling your UI from the application process, your widgets are safely serialized and easily rendered on a wide range of Android devices, sorry. [02:19](https://www.youtube.com/watch?v=5--1viVciq4&t=139s) This means you can bring this rich experiences to pretty much all the supported remote surfaces with minimal efforts. ### Layout sizes and backward compatibility [02:29](https://www.youtube.com/watch?v=5--1viVciq4&t=149s) To make the transition from Tiles to widgets as smooth as possible, we are introducing two standard container sizes: small and large. [02:38](https://www.youtube.com/watch?v=5--1viVciq4&t=158s) These are designed to be closely aligned to the two-by-one and two-by-two grid-based widget formats that you're already used to by building widgets on mobile. [02:49](https://www.youtube.com/watch?v=5--1viVciq4&t=169s) And starting on Wear 7 on some hardware manufacturers, your Wear Widgets will now live in a vertically-scrolling tray alongside the widgets of other apps. [02:59](https://www.youtube.com/watch?v=5--1viVciq4&t=179s) For instance, this is how Wear Widgets look like on a Samsung Galaxy Watch. [03:04](https://www.youtube.com/watch?v=5--1viVciq4&t=184s) The platform architecture is built to support vertically-scrolling trays as hardware manufacturers adopt this pattern in the future. [03:12](https://www.youtube.com/watch?v=5--1viVciq4&t=192s) And you don't need to worry about leaving any users, or existing users, behind. [03:16](https://www.youtube.com/watch?v=5--1viVciq4&t=196s) The Jetpack Glance Wear APIs are designed to support backward compatibility down to Wear 4. [03:22](https://www.youtube.com/watch?v=5--1viVciq4&t=202s) On older devices that support a horizontal tray of widgets, or of Tiles, the system will handle that for you. [03:31](https://www.youtube.com/watch?v=5--1viVciq4&t=211s) You simply need to state in your code that you want to support full-screen mode, and the system will take your large widget and display it as a full-screen traditional Tiles on these devices. [03:41](https://www.youtube.com/watch?v=5--1viVciq4&t=221s) Now, Yuri is going to walk us through the code to show you exactly how to migrate your existing Tiles into Wear Widgets. ### Migration strategies for existing tiles [03:50](https://www.youtube.com/watch?v=5--1viVciq4&t=230s) Thanks, Frank. [03:52](https://www.youtube.com/watch?v=5--1viVciq4&t=232s) If you're building a new Wear Widget from scratch, it's simple. [03:56](https://www.youtube.com/watch?v=5--1viVciq4&t=236s) You just define a GlanceWearWidgetService and build your UI using Remote Compose. [04:04](https://www.youtube.com/watch?v=5--1viVciq4&t=244s) But if your app already has a Tile in production, you'll need to migrate both your services, UI, and data. [04:14](https://www.youtube.com/watch?v=5--1viVciq4&t=254s) To make this transition as smooth as possible, we've provided paths to ensure a seamless experience for existing users. [04:22](https://www.youtube.com/watch?v=5--1viVciq4&t=262s) For the service, you can choose between two strategies: dual service or single service. [04:30](https://www.youtube.com/watch?v=5--1viVciq4&t=270s) With dual service, which we recommend, you'll keep your existing TileService for older Wear OS devices and add a new GlanceWearWidgetService for Wear OS 7+. [04:43](https://www.youtube.com/watch?v=5--1viVciq4&t=283s) In contrast, with the single service, you create a new, single GlanceWearWidgetService that handle both protocols, running in a compatibility mode to translate your widget into a Tile on older devices. [04:57](https://www.youtube.com/watch?v=5--1viVciq4&t=297s) Either way, you'll continue to reach your users. [05:00](https://www.youtube.com/watch?v=5--1viVciq4&t=300s) It just affects what code you maintain going forward. [05:06](https://www.youtube.com/watch?v=5--1viVciq4&t=306s) And we've just published comprehensive documentation on the Android developer site detailing exactly how and when to use both these patterns. [05:15](https://www.youtube.com/watch?v=5--1viVciq4&t=315s) Check it out to learn more about which strategy is best for your app. ### Building UI with Remote Compose [05:22](https://www.youtube.com/watch?v=5--1viVciq4&t=322s) Now let's talk about the UI layer. [05:25](https://www.youtube.com/watch?v=5--1viVciq4&t=325s) When migrating, your mental model shifts. [05:27](https://www.youtube.com/watch?v=5--1viVciq4&t=327s) Previously, tiles use ProtoLayout, a library built exclusively for Wear tiles. [05:33](https://www.youtube.com/watch?v=5--1viVciq4&t=333s) Wear Widgets, on the other hand, builds on Remote Compose. [05:37](https://www.youtube.com/watch?v=5--1viVciq4&t=337s) Remote Compose shares exact the same foundation as Jetpack Compose UI, using the same core compiler and runtime. [05:45](https://www.youtube.com/watch?v=5--1viVciq4&t=345s) And it's designed to feel familiar, closely matching Compose UI libraries like foundation and Material 3. [05:53](https://www.youtube.com/watch?v=5--1viVciq4&t=353s) But instead of a box, column, or text, you'll simply swap them for `RemoteBox`, `RemoteColumn`, or `RemoteText`. [06:02](https://www.youtube.com/watch?v=5--1viVciq4&t=362s) You'll get familiar with writing "remote" a lot in this case. [06:08](https://www.youtube.com/watch?v=5--1viVciq4&t=368s) Plus to speed up your workflow, we've included a full set of ready-to-use Remote Compose components designed specifically for widgets. [06:17](https://www.youtube.com/watch?v=5--1viVciq4&t=377s) This means your existing Wear Material 3 designs, including what you've got in Figma, can be easily adapted to widgets, making this familiar to both engineers and designers. [06:31](https://www.youtube.com/watch?v=5--1viVciq4&t=391s) To see just how aligned these frameworks are, let's look at a concrete example. [06:35](https://www.youtube.com/watch?v=5--1viVciq4&t=395s) We're going to build our own app component on top of Material 3 switch button. [06:40](https://www.youtube.com/watch?v=5--1viVciq4&t=400s) On the left, we have the standard Wear Compose component you'd write inside your app, and on the right is the Remote Compose version. ```kotlin // Wear Compose @Composable fun HistoryEraserButton( onClick: () -> Unit, modifier: Modifier = Modifier, checked: Boolean = true, onCheckedChange: (Boolean) -> Unit = {}, ) ``` ```kotlin // Wear RemoteCompose @RemoteComposable @Composable fun RemoteHistoryEraserButton( onClick: Action, modifier: RemoteModifier = RemoteModifier, checked: RemoteBoolean = true.rb, onCheckedChange: Action = Action.Empty, ) ``` [06:52](https://www.youtube.com/watch?v=5--1viVciq4&t=412s) Notice how similar the patterns are. [06:55](https://www.youtube.com/watch?v=5--1viVciq4&t=415s) When writing Remote Compose code, however, you'll use the `RemoteComposable` annotation. [07:02](https://www.youtube.com/watch?v=5--1viVciq4&t=422s) And where you use familiar params like modifier and boolean, they have equivalent Remote Compose types like `RemoteModifier` and `RemoteBoolean`. [07:15](https://www.youtube.com/watch?v=5--1viVciq4&t=435s) And you use actions instead of lambdas. [07:18](https://www.youtube.com/watch?v=5--1viVciq4&t=438s) Instead of defining the execute to the code to execute inside the lambda, you'll need to declare an action such as launching a pending intent, calling a service, or updating a value. [07:32](https://www.youtube.com/watch?v=5--1viVciq4&t=452s) Let's jump to the body of our component. [07:35](https://www.youtube.com/watch?v=5--1viVciq4&t=455s) You'll notice even the theming is aligned. [07:39](https://www.youtube.com/watch?v=5--1viVciq4&t=459s) You can apply your Material 3 color scheme to the Remote Compose component exactly as you would in standard Compose, which lets your widget exactly match your app's branding. ```kotlin // 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!") }, ) ``` ```kotlin // 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) }, ) ``` [07:53](https://www.youtube.com/watch?v=5--1viVciq4&t=473s) And finally, let's see the result. The resulting UI is exactly what you'd expect, a clean, responsive, animated toggle button. ### Compose preview support for widgets [08:04](https://www.youtube.com/watch?v=5--1viVciq4&t=484s) It's hard to tell the difference. [08:08](https://www.youtube.com/watch?v=5--1viVciq4&t=488s) To help you design, iterate, and verify your widget layouts without always running on a device or emulator, we've added Compose preview support for Wear Widgets. [08:20](https://www.youtube.com/watch?v=5--1viVciq4&t=500s) Because widgets depend on OEM specific container constraints, such as size, shape, padding, corner radius, we build on the standard preview annotation, but with an additional parameter provider to inject these configurations. ```kotlin @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) ``` [08:38](https://www.youtube.com/watch?v=5--1viVciq4&t=518s) The library provides preconfigured `PreviewParameter` provider implementations that match real-world Wear OS devices. [08:50](https://www.youtube.com/watch?v=5--1viVciq4&t=530s) These preview annotations let you easily verify your layout across very various different hardware shapes. [08:58](https://www.youtube.com/watch?v=5--1viVciq4&t=538s) Beyond testing your layouts, you can use these previews to generate the static images required for the on-device widget picker. ```kotlin @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) ``` [09:05](https://www.youtube.com/watch?v=5--1viVciq4&t=545s) The library provides a parameter for rectangular preview shape which emulates the full uncropped rectangular containers. ### Sample implementation and migration tools [09:17](https://www.youtube.com/watch?v=5--1viVciq4&t=557s) And if you want to see how exactly this works in practice, we've refreshed our Horologist media sample app to include a new widget that showcases this API. [09:27](https://www.youtube.com/watch?v=5--1viVciq4&t=567s) We show how to add both the small and large versions of the media widget. [09:35](https://www.youtube.com/watch?v=5--1viVciq4&t=575s) Check it out on GitHub to see side-by-side the comparison of the legacy ProtoLayout code and the new Remote Compose implementation. [09:43](https://www.youtube.com/watch?v=5--1viVciq4&t=583s) We're sure you'll like it. [09:47](https://www.youtube.com/watch?v=5--1viVciq4&t=587s) Finally, this wouldn't be a, you know, a talk without mentioning AI. [09:52](https://www.youtube.com/watch?v=5--1viVciq4&t=592s) To speed up your migration, we've published a new tiles to widgets migration skill on GitHub. [09:58](https://www.youtube.com/watch?v=5--1viVciq4&t=598s) You can use it with your agent of choice, or you can add it directly to Android Studio using the Android CLI. ```shell android skills add wear-widgets android skills add --all ``` [10:04](https://www.youtube.com/watch?v=5--1viVciq4&t=604s) Now I'll hand you back to François to wrap things up. ### Summary and wrap-up [10:12](https://www.youtube.com/watch?v=5--1viVciq4&t=612s) Thank you. [10:12](https://www.youtube.com/watch?v=5--1viVciq4&t=612s) Thank you, Yuri. [10:13](https://www.youtube.com/watch?v=5--1viVciq4&t=613s) So as you can see, evolving your tiles into Wear Widgets is a very straightforward process. [10:19](https://www.youtube.com/watch?v=5--1viVciq4&t=619s) To recap, by migrating to Jetpack Glance Wear and Remote Compose, you are not simply updating your UI, you are joining a more unified Android widgets ecosystem. [10:31](https://www.youtube.com/watch?v=5--1viVciq4&t=631s) You can now build beautiful, backward compatible widgets using a modern, declarative framework fully aligned with Jetpack Compose. [10:40](https://www.youtube.com/watch?v=5--1viVciq4&t=640s) You can start migrating your tiles today by heading over to the Getting Started guide on Android Developers site for more-- for all the details. [10:50](https://www.youtube.com/watch?v=5--1viVciq4&t=650s) We look forward to seeing all the expressive, glanceable experiences you build for the wrist. [10:55](https://www.youtube.com/watch?v=5--1viVciq4&t=655s) Thank you very much for joining us today, this morning, and we hope you enjoy the rest of the conference. [11:01](https://www.youtube.com/watch?v=5--1viVciq4&t=661s) Thank you.