This codelab shows how easy it is to create your own Wear OS analog watch face using Kotlin DSL (domain-specific language). By the end of the codelab, you'll have a customized watch face that you can call your own.

Concepts and setup

Concepts

A domain-specific language (DSL) is a "language specialized to a particular application domain". A DSL is a way to deal with a specific set of concerns. In our case, it's used to help us create watch faces.

In this codelab, we show how to use a DSL to greatly simplify the creation of watch faces.

Let's start by learning a little about Wear OS and its most prominent UI element - the watch face.

Wear OS by Google is designed for small, powerful devices, worn on the body. It is designed to deliver useful information when you need it most, intelligent answers to spoken questions, and tools to help reach fitness goals.

Style is a big part of such a personal device. Aside from offering a choice of manufacturers, customisable watch faces give users even more ways to express their personal style, and we will help you create your own today.

A watch face is essentially a native service that runs in the background on a Wear OS device. Within this service, there is an engine that renders each screen. You can think of this as an animator flipping through a book of moving cartoon drawings.

You normally write code that manually draws each of these pages (making the watch face move). However, we will use Kotlin DSL to greatly simplify the process.

Let's get started!

Clone the starter project repo

To help you get you started quickly, we have prepared a project for you to build on. It contains some basic code and application settings necessary for building watch faces.

If you have Git installed, run the command below. (You can check by typing git --version in the terminal / command line and verify that it executes correctly.)

 git clone https://github.com/googlecodelabs/watchface-kotlin

If you do not have git you can get the project as a zip file:

Download Zip

Import the project

Start Android Studio and select "Open an existing Android Studio project" from the Welcome screen. Open the project directory and double click the build.gradle file in the WatchFaceKotlin directory:

After the project has loaded, you may see an alert saying, "Unregistered VCS root detected". Click "Ignore" or the "X" in the upper-right corner. (You won't be pushing any changes back to the Git repo.)

In the upper-left corner of the project window, if you are in the Android view, you should see a set of folder icons similar to those in the screenshot below. (If you are in the Project view, expand the WatchFaceKotlin project to see the set of folder icons.)

There are two folder icons (base and complete). Each folder icon represents a "module". Please note that Android Studio might take several seconds to compile the project in the background for the first time. During this time you will see a spinner in the status bar at the bottom of Android Studio:

Wait until the processes finish before making code changes, to allow Android Studio to pull in all the necessary components.

In addition, if you get a prompt saying "Reload for language changes to take effect?" or something similar, select "Yes".

Understand the starter project

You're ready to create a watch face. You'll start in the base module and build a watch face on top of that code. You'll add code from each step to base.

The complete module can be used for any needed reference points for checking your work, or for reference if you encounter any issues.

Overview of key components:

Emulator setup

If you need help setting up a Wear OS emulator, please refer to Launch a Wear emulator and run your Wear app.

Emulator setup

Some stations have Wear devices. If you are at a station that does not have a Wear device and need help setting up a Wear OS emulator, please refer to Launch a Wear emulator and run your Wear app.

Run the starter project

Let's run the watch face on a watch.


$ adb install-multiple -r -t
... lots of stuff ...
Split APKs installed

Please note, since this is the first time you are running this watch face, you will need to select it from "Add more watch faces". After it has been selected once, it will show up as one of the options alongside this option.

04-27 15:40:00.879 14459-14459/com.example.android.watchface.watchfacekotlin E/AndroidRuntime: FATAL EXCEPTION: main

...

Caused by: java.lang.InstantiationException: Must define watch face styles in DSL.

at com.example.android.watchface.watchfacekotlin.service.AnalogWatchFaceStyleBuilder.build(WatchFaceStyleDsl.kt:146)

at

....

Don't worry if your emulator has a cloud with a strikethrough in place of the airplane icon. We will not need a connection to a phone / internet for this code lab.

Summary

In this step you've learned about:

Next up

Let's start making this watch face our own.

Code step 2

In this section, you will create watch hands and color for your watch face.

Prepare the paint objects

Just kidding, using Kotlin + DSL will help us avoid manual painting canvases in this codelab!

Define your main color

In the base module, open the AnalogDslWatchFace file and look at analogWatchFaceStyle {}. It should look like this:

return analogWatchFaceStyle { }

Let's define the colors:

return analogWatchFaceStyle {
    watchFaceColors {
        main = Color.GREEN
    }
}

Define your arm dimensions

Now that we have the main color set, let's define the length of the hour, minute, and second watch arms:

return analogWatchFaceStyle {
    watchFaceColors {
        main = Color.GREEN
    }
    watchFaceDimensions {
        hourHandRadiusRatio = 0.2f
        minuteHandRadiusRatio = 0.5f
        secondHandRadiusRatio = 0.9f
    }
}

Check your progress

Choose the Kotlin DSL Analog watch face in the Favorites menu:

You should see something like this:

Define more colors

Let's customize more colors in our watch face:

return analogWatchFaceStyle {
   watchFaceColors {
       main = Color.GREEN
       highlight = Color.parseColor("#BB0000")
       background = Color.WHITE
   }
   watchFaceDimensions {
       hourHandRadiusRatio = 0.2f
       minuteHandRadiusRatio = 0.5f
       secondHandRadiusRatio = 0.9f
   }
}

Check your progress

If you run the watch face now and reselect Kotlin DSL Analog, you should see a watch face similar to the image below.

Summary

In this step, you've learned:

Next up

We will further customize our watch face by setting a background image.

Code step 3

In this step, we add a background image to our watch face. If at any point you are confused by the concepts discussed here, please refer to the complete module and see how these steps may be implemented.

Prepare your image

A background image is supplied in this code lab. However, you can prepare your own image.

To use your own image, select any photograph, but note that some images with tiny details may not scale well on a small watch display. Crop the image to a square shape and resize it to about 600 x 600 pixels. It can be in JPEG or PNG format. Then rename it to background_image.jpg or background_image.png (Android needs an underscore in place of a space).

After you completed this, "right click" the res/drawable directory in Android Studio and select "Reveal in Finder" (for Mac) or "Show in Explorer" (for Windows). Copy your image file into the directory res/drawable. It will replace the default image already in the folder.

Set a background image

Open the AnalogDslWatchFace file and look again at analogWatchFaceStyle {}. It should look like this:

return analogWatchFaceStyle {
   watchFaceColors {
       main = Color.GREEN
       highlight = Color.parseColor("#BB0000")
       background = Color.WHITE
   }
   watchFaceDimensions {
       hourHandRadiusRatio = 0.2f
       minuteHandRadiusRatio = 0.5f
       secondHandRadiusRatio = 0.9f
   }
}

Let's add a background image:

return analogWatchFaceStyle {
   watchFaceColors {
       main = Color.CYAN
       highlight = Color.parseColor("#ffa500")
       background = Color.WHITE
   }
   watchFaceDimensions {
       hourHandRadiusRatio = 0.2f
       minuteHandRadiusRatio = 0.5f
       secondHandRadiusRatio = 0.9f
   }
   watchFaceBackgroundImage {
       backgroundImageResource = R.drawable.background_image
   }
}

Check your progress

If you run the watch face now and reselect Kotlin DSL Analog, you should see something like the image below.

Summary

In this step you've learned to:

Try customizing your watch face even further using DSL by reviewing all the options in the model/AnalogWatchFaceStyleModels.kt class.

As stated earlier, DSLs (domain-specific languages) are "languages specialized to a particular application domain". To learn more about Kotlin DSL, read the Type-Safe Builders page on the Kotlin site.

You can see how the watch face DSL was implemented for this code lab by reviewing the service/WatchFaceStyleDsl.kt class.

If you are interested in how the object that was created with DSL is rendered into a watch face, review the service/AbstractKotlinWatchFace.kt class.

For more details about developing Wear OS watch faces and data providers (and how Java development compares to this code lab), please review

Learn More

Watch these great videos: