WatchFaceService

public abstract class WatchFaceService

Known direct subclasses

WatchFaceService and WatchFace are a pair of classes intended to handle much of the boilerplate needed to implement a watch face without being too opinionated. The suggested structure of a WatchFaceService based watch face is:

import android.graphics.RectF
import androidx.wear.watchface.complications.ComplicationSlotBounds
import androidx.wear.watchface.complications.DefaultComplicationDataSourcePolicy
import androidx.wear.watchface.CanvasComplicationFactory
import androidx.wear.watchface.ComplicationSlotsManager
import androidx.wear.watchface.WatchFace
import androidx.wear.watchface.complications.rendering.CanvasComplicationDrawable
import androidx.wear.watchface.complications.rendering.ComplicationDrawable
import androidx.wear.watchface.style.UserStyleSchema
import androidx.wear.watchface.style.UserStyleSetting.ListUserStyleSetting

class ExampleCanvasWatchFaceService : WatchFaceService() {
    override fun createUserStyleSchema() =
        UserStyleSchema(
            listOf(
                ListUserStyleSetting(
                    UserStyleSetting.Id("color_style_setting"),
                    "Colors",
                    "Watchface colorization",
                    icon = null,
                    options = listOf(
                        ListUserStyleSetting.ListOption(
                            Option.Id("red_style"),
                            "Red",
                            icon = null
                        ),
                        ListUserStyleSetting.ListOption(
                            Option.Id("green_style"),
                            "Green",
                            icon = null
                        ),
                        ListUserStyleSetting.ListOption(
                            Option.Id("blue_style"),
                            "Blue",
                            icon = null
                        )
                    ),
                    listOf(
                        WatchFaceLayer.BASE,
                        WatchFaceLayer.COMPLICATIONS,
                        WatchFaceLayer.COMPLICATIONS_OVERLAY
                    )
                ),
                ListUserStyleSetting(
                    UserStyleSetting.Id("hand_style_setting"),
                    "Hand Style",
                    "Hand visual look",
                    icon = null,
                    options = listOf(
                        ListUserStyleSetting.ListOption(
                            Option.Id("classic_style"), "Classic", icon = null
                        ),
                        ListUserStyleSetting.ListOption(
                            Option.Id("modern_style"), "Modern", icon = null
                        ),
                        ListUserStyleSetting.ListOption(
                            Option.Id("gothic_style"),
                            "Gothic",
                            icon = null
                        )
                    ),
                    listOf(WatchFaceLayer.COMPLICATIONS_OVERLAY)
                )
            )
        )

    override fun createComplicationSlotsManager(
        currentUserStyleRepository: CurrentUserStyleRepository
    ): ComplicationSlotsManager {
        val canvasComplicationFactory =
            CanvasComplicationFactory { watchState, listener ->
                CanvasComplicationDrawable(ComplicationDrawable(this), watchState, listener)
            }
        return ComplicationSlotsManager(
            listOf(
                ComplicationSlot.createRoundRectComplicationSlotBuilder(
                    /*id */ 0,
                    canvasComplicationFactory,
                    listOf(
                        ComplicationType.RANGED_VALUE,
                        ComplicationType.LONG_TEXT,
                        ComplicationType.SHORT_TEXT,
                        ComplicationType.MONOCHROMATIC_IMAGE,
                        ComplicationType.SMALL_IMAGE
                    ),
                    DefaultComplicationDataSourcePolicy(
                        SystemDataSources.DATA_SOURCE_DAY_OF_WEEK,
                        ComplicationType.SHORT_TEXT
                    ),
                    ComplicationSlotBounds(RectF(0.15625f, 0.1875f, 0.84375f, 0.3125f))
                ).build(),
                ComplicationSlot.createRoundRectComplicationSlotBuilder(
                    /*id */ 1,
                    canvasComplicationFactory,
                    listOf(
                        ComplicationType.RANGED_VALUE,
                        ComplicationType.LONG_TEXT,
                        ComplicationType.SHORT_TEXT,
                        ComplicationType.MONOCHROMATIC_IMAGE,
                        ComplicationType.SMALL_IMAGE
                    ),
                    DefaultComplicationDataSourcePolicy(
                        SystemDataSources.DATA_SOURCE_STEP_COUNT,
                        ComplicationType.SHORT_TEXT
                    ),
                    ComplicationSlotBounds(RectF(0.1f, 0.5625f, 0.35f, 0.8125f))
                ).build()
            ),
            currentUserStyleRepository
        )
    }

    override suspend fun createWatchFace(
        surfaceHolder: SurfaceHolder,
        watchState: WatchState,
        complicationSlotsManager: ComplicationSlotsManager,
        currentUserStyleRepository: CurrentUserStyleRepository
    ) = WatchFace(
        WatchFaceType.ANALOG,
        object : Renderer.CanvasRenderer(
            surfaceHolder,
            currentUserStyleRepository,
            watchState,
            CanvasType.HARDWARE,
            /* interactiveUpdateRateMillis */ 16,
        ) {
            init {
                // Listen for user style changes.
                CoroutineScope(Dispatchers.Main.immediate).launch {
                    currentUserStyleRepository.userStyle.collect {
                        // `userStyle` will contain two userStyle categories with options
                        // from the lists above. ..
                    }
                }
            }

            override fun render(
                canvas: Canvas,
                bounds: Rect,
                zonedDateTime: ZonedDateTime
            ) {
                // ...
            }

            override fun renderHighlightLayer(
                canvas: Canvas,
                bounds: Rect,
                zonedDateTime: ZonedDateTime
            ) {
                canvas.drawColor(renderParameters.highlightLayer!!.backgroundTint)

                // ...
            }
        }
    )
}

return ExampleCanvasWatchFaceService()

Sub classes of WatchFaceService are expected to implement createWatchFace which is the factory for making WatchFaces. If the watch faces uses complications then createComplicationSlotsManager should be overridden. All ComplicationSlots are assumed to be enumerated up upfront and passed as a collection into ComplicationSlotsManager's constructor which is returned by createComplicationSlotsManager.

Watch face styling (color and visual look of watch face elements such as numeric fonts, watch hands and ticks, etc...) and companion editing is directly supported via UserStyleSchema and UserStyleSetting. To enable support for styling override