Getting Started With the New Wear OS Tiles API

Parthiv S Vora
CapTech Corner
Published in
6 min readMay 28, 2021

At Google I/O this year, Google officially announced the release of the new Tiles API for Wear OS. While it was announced as an alpha release a few months ago, Google’s rolling out support for Tiles into production in the coming months. The Tiles API is part of a larger update to Wear OS, including updating Wear OS to be based on Android 11 and partnering with Samsung to include key Tizen features.

Let’s step through creating a simple Wear app that leverages the Tiles API.

Setting Up

To start, ensure that you have installed the Android 11 SDK along with the Wear OS Preview System Image through the SDK Manager in Android Studio Once you have that installed, go ahead and create a new virtual device using the Wear OS Preview System Image.

Next, create a new Android Studio project. In the New Project window, select Wear OS -> Blank Activity.

On the next page, name your application and package as you wish but select API 30 for the Minimum SDK — this is the API Level that is required by the Tiles API. This example won’t depend on a companion phone app, so you can leave the option for that unchecked for now.

Once your project is created, you’ll need to add the appropriate dependencies for the Wear app. Find the build.gradle file in the watch app module and add the lines below in the dependencies block.

The first dependency above is for Guava, which is required by the Tiles API. This dependency tripped me up at first; the official docs don’t mention you need it, but after encountering errors and digging through some source code I found it to be required. The second dependency is the actual Tiles API, and the third is for some debugging tools you can use to preview your Tiles (since Wear OS still doesn’t have user support for Tiles).

Since we can’t preview Tiles normally through Wear OS yet, we have to set up a debug preview, which you can do in an Activity by adding a FrameLayout like the one below to its layout XML.

Next, open up your chosen preview Activity, and add the code below. Since Wear OS doesn’t have a way to actually display your Tile to a user yet, we need to set up a TileClient, which allows you to view your Tile within your app itself. We’re also going to add some code to the onCreate() and onDestroy() functions to handle the lifecycle calls that the TileClient needs.

You’ll notice MainTileService will give an “unresolved reference” error. Don’t worry, we’ll define that next.

Building a Basic Tile

First, add the below service to your Android Manifest. You can see we’re declaring a permission the app requires to create Tiles, as well as an intent filter that tells Android we have a Tile it can hook into. The meta data at the bottom is just for the preview your Tile will eventually have when Wear OS supports users selecting Tiles. The drawable in there is just a placeholder for now but you would normally replace this with your own drawable resource, which should be a preview or screenshot of your Tile.

Now, we’re ready to create our MainTileService, which is where we’ll actually define the Tile. Create a new Kotlin class, MainTileService, that extends TileProviderService, the base class for any service that defines Tiles. The TileProviderService class defines two functions you have to override, onTileRequest() and onResourcesRequest(). Add the onTileRequest() function below:

onTileRequest() defines your actual Tile, and this is where the bulk of your Tile’s definition goes. First, note that the whole thing is wrapped in Futures.immedateFuture(). That’s because both functions return a ListenableFuture, but the builders return the actual object you’ll need. Take a look at the Tile.builder. This is how your Tile is created. Each Tile must contain a single Timeline. This Timeline can have one or more TimelineEntries with their own Layout.

Right now, our Tile has a Timeline with a single TimelineEntry, which contains a Layout with a Text element. Something important you may have noticed: the Tile’s Layout doesn’t use an XML layout resource. Instead, you define all your Layouts declaratively.

Meanwhile, onResourcesRequest() defines resources your Tile will use, such as images. Tiles don’t have access to your application’s resources, so you have to define them manually using the Resources.builder object. The TileProviderService requires this function to be defined, so here’s a basic version of the function you can use, that doesn’t define any resources:

Let’s test it out: build and run your project in the emulator. Your preview Activity should pop up with your Tile displayed.

Make Your Tile Tappable

Let’s take it a step further and add the ability to tap on your Tile to change what it displays. We’ll refactor it to use two layout objects: one that’s displayed by default, and one that shows after you tap on the Tile.

First, add the following two constants to the top of your MainTileService file. These are just strings to identify the two layouts we’re using.

Now add this function inside MainTileService:

All this function does is return a tappable Layout with the given text and ID values. To make the Layout tappable, you can see we’re adding Modifiers to it, and inside the Modifiers, we’re setting the Clickable property. The ID we pass to the Clickable builder identifies the Layout that was tapped, so we can decide what to do when the Tile loads, based on which Layout we were looking at. The LoadAction.builder() call is what actually refreshes the Tile to swap Layouts when the Tile is tapped.

Finally, inside the onTileRequest() function, change the contents of Layout.builder().setRoot(…), removing the Text builder and replacing it with a when block:

Here, requestParams.state.lastClickableId is the ID of the Layout that was tapped, the same ID we’re setting inside the Clickable builder inside the tappableLayout() function. If the ID of the Layout that was clicked is the default one, we return the LayoutElement for the alternate Layout, to switch it back to the alternate one. Otherwise, if the alternate one was clicked, or the Tile was just loaded (in which case the lastClickableId value will be null), we return the default LayoutElement.

Here’s what it looks like in action:

That’s all there is to it! You now have a basic tappable Tile.

Tons of Options

You’re not limited to just text and tapping; you can do all kinds of fun things with your Tiles. The Tiles API is very robust, providing support for plenty of different customizations. You can set up different TimelineEntries to show a different Layout for different blocks of time, add colors and images, and customize your Layouts in various ways. You can even make curved text! For example, you can make Tiles like the ones in the animation below:

Image source: https://android-developers.googleblog.com/2021/03/creating-custom-tiles-on-wear-os-by-google-with-jetpack-tiles.html

You can learn more about the Tiles API here, and if you’re looking for ideas, Google has a repository of sample Tiles you can find here.

--

--

Parthiv S Vora
CapTech Corner

Lead Software Engineer at Cox Automotive. I work on all kinds of stuff. https://parthivsvora.com