What You'll Learn
Wear OS Tiles (TileService, layout building, data update, click actions, preview) explained.
Setup
dependencies {
implementation("androidx.wear.tiles:tiles:1.4.1")
implementation("androidx.wear.tiles:tiles-material3:1.4.1")
implementation("androidx.wear.tiles:tiles-tooling-preview:1.4.1")
debugImplementation("androidx.wear.tiles:tiles-tooling:1.4.1")
}
TileService
class StepsTileService : TileService() {
override suspend fun tileRequest(requestParams: RequestBuilders.TileRequest): TileBuilders.Tile {
val steps = getStepsFromDataStore()
return TileBuilders.Tile.Builder()
.setResourcesVersion("1")
.setTileTimeline(
TimelineBuilders.Timeline.Builder()
.addTimelineEntry(
TimelineBuilders.TimelineEntry.Builder()
.setLayout(
LayoutElementBuilders.Layout.Builder()
.setRoot(createLayout(steps))
.build()
)
.build()
)
.build()
)
.setFreshnessIntervalMillis(300_000) // Update every 5 minutes
.build()
}
override suspend fun resourcesRequest(
requestParams: RequestBuilders.ResourcesRequest
): ResourceBuilders.Resources {
return ResourceBuilders.Resources.Builder()
.setVersion("1")
.addIdToImageMapping("icon_walk", ResourceBuilders.ImageResource.Builder()
.setAndroidResourceByResId(
ResourceBuilders.AndroidImageResourceByResId.Builder()
.setResourceId(R.drawable.ic_walk)
.build()
).build()
)
.build()
}
private fun createLayout(steps: Int): LayoutElementBuilders.LayoutElement {
return LayoutElementBuilders.Column.Builder()
.addContent(
LayoutElementBuilders.Image.Builder()
.setResourceId("icon_walk")
.setWidth(DimensionBuilders.dp(24f))
.setHeight(DimensionBuilders.dp(24f))
.build()
)
.addContent(
LayoutElementBuilders.Text.Builder()
.setText("$steps")
.setFontStyle(
LayoutElementBuilders.FontStyle.Builder()
.setSize(DimensionBuilders.sp(32f))
.setWeight(LayoutElementBuilders.FONT_WEIGHT_BOLD)
.build()
)
.build()
)
.addContent(
LayoutElementBuilders.Text.Builder()
.setText("steps")
.setFontStyle(
LayoutElementBuilders.FontStyle.Builder()
.setSize(DimensionBuilders.sp(14f))
.build()
)
.build()
)
.setHorizontalAlignment(LayoutElementBuilders.HORIZONTAL_ALIGN_CENTER)
.build()
}
}
Manifest Registration
<service
android:name=".StepsTileService"
android:exported="true"
android:permission="com.google.android.wearable.permission.BIND_TILE_PROVIDER">
<intent-filter>
<action android:name="androidx.wear.tiles.action.BIND_TILE_PROVIDER" />
</intent-filter>
<meta-data
android:name="androidx.wear.tiles.PREVIEW"
android:resource="@drawable/tile_preview" />
</service>
Click Actions
private fun createClickableLayout(): LayoutElementBuilders.LayoutElement {
val clickable = ModifiersBuilders.Clickable.Builder()
.setOnClick(
ActionBuilders.LaunchAction.Builder()
.setAndroidActivity(
ActionBuilders.AndroidActivity.Builder()
.setClassName("com.example.MainActivity")
.setPackageName("com.example.app")
.build()
)
.build()
)
.setId("open_app")
.build()
return LayoutElementBuilders.Box.Builder()
.addContent(/* content */)
.setModifiers(
ModifiersBuilders.Modifiers.Builder()
.setClickable(clickable)
.build()
)
.build()
}
Tile Update Trigger
// Request tile update on data change
class StepsRepository @Inject constructor(context: Context) {
fun updateSteps(steps: Int) {
// Save data
saveSteps(steps)
// Request tile update
TileService.getUpdater(context).requestUpdate(StepsTileService::class.java)
}
}
Summary
| Feature | Implementation |
|---|---|
| Tile definition | TileService |
| Layout | LayoutElementBuilders |
| Resources | ResourceBuilders |
| Click | LaunchAction |
| Update | TileService.getUpdater() |
-
TileServicedefines Wear OS tiles -
LayoutElementBuildersconstructs UI -
freshnessIntervalMillisfor periodic update -
requestUpdate()for immediate tile update
Ready-Made Android App Templates
8 production-ready Android app templates with Jetpack Compose, MVVM, Hilt, and Material 3.
Browse templates → Gumroad
Top comments (0)