Create a watchface for Wear OS

1. Create your first watch face

This codelab will introduce you to the key concepts needed to create your own watch face for Wear OS. It will then walk you through customising an analog watch face. There is also a bonus section on using the palette API to automatically choose a color for the watch face if you have the time. By the end of the codelab, you'll have a customized watch face that you can call your own.

Concepts and setup

In this codelab, you'll learn how to quickly create a watch face for Wear OS. At the end of the codelab, you can expect to have a watch face you can call your own.


To start off let's learn a little bit about Wear OS and its most prominent UI element - the watch face.


Wear OS is a wearable platform 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.

Being such a personal device, style is a big part of it. Aside from offering a choice of manufacturers, customisable watch faces give users even more ways to express their personal style. This is what we are going to create today.

A watch face is essentially a native service that runs in the background on an 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. Our code will fill each of these pages, making the watch face move.

So let's get started!

If you run into any issues (code bugs, grammatical errors, unclear wording, etc.) as you work through this codelab, please report the issue via the Report a mistake link in the lower left corner of the codelab.

Clone the starter project repo

To get you started as quickly as possible, we have prepared a starter project for you to build on. It contains some basic code and application settings necessary for building watch faces. If you have git installed, you can simply run the command below. (You can check by typing git --version in the terminal / command line and verify it executes correctly.)

 git clone

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

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 on the build.gradle file in the watchface directory:


After the project has loaded, you may also see an alert like the one below, you can click "X" in the upper right. (You won't be pushing any changes back to the Git repo.)

Screen Shot 2016-05-17 at 10.17.48 AM.png

In the upper-left corner of the project window, you should see something like the image below if you are in the Android view. (If you are in the Project view, you will need to expand the watchface project to see the same thing.)


There are five folder icons. Each of them are known as 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:


We recommend that you wait until this has finished before making code changes. This will 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

All right, you're set up and ready to start creating your own watch face. We'll set off using the 1-base module, which is the starting point for the watch face that we'll be building upon. You will be adding code from each step to 1-base.

Each of the following modules can be used as reference points to check your work or for reference if you encounter any issues. The number in front of the module name corresponds with the codelab step.

Overview of key components

  • MyWatchFaceService - Our watch face and it has a watch face engine called MyWatchFaceService.Engine - This file is located in the directory 1-base/java/com/android/example/watchface. In Android Studio, this is located under 1-base/java/
  • Within the Engine class, we will mainly be working on three methods:
  • onCreate - We will initiate new classes such as the bitmap image object for our background, etc. This code is run once when the Engine is first started.
  • onSurfaceChanged - This is the first time when we have the dimension of the screen. Armed with this new information, we can resize any screen element required for drawing. This code is also expected to only be run once at the start.
  • onDraw - The core of what we will be doing. It renders every frame on the watch face canvas. Since it runs on every frame, we will try to keep this as fast as possible - no image resizing or object creation here!
  • res/drawable-nodpi/ - This is the directory where we will be placing some additional image files.

Emulator setup

If you need help setting up an Wear OS emulator, please refer to the "Set Up an Wear OS Emulator or Device" section of the "Creating and Running a Wearable App" article.

Run the starter project

Let's run it on a watch.

  • Connect your Wear OS device or start an emulator.
  • In the toolbar, select the "1-base"configuration from the drop down and click the green triangle run button next to it:


  • If you get an error like the one below (Error running 1-base: Default Activity not found), you will need to change the default launch Activity (instructions below).

d0c11ad6503d05c0.png Conversely, you may be asked directly which Activity to use when launching the app, choose "Do not launch Activity".

  • To change the default launch Activity (if you need to do this from previous step), click on the drop down to the left of the green arrow and click "edit configurations". 839a1df348361f30.png

Select "1-base" and you will see a window similar the one below. Under the "Launch Options" section, there will be a set of dropdown options. Select "Nothing" under the "Launch Options" section and click OK. Once the prompt dismisses, you will need to click the green triangle again to run the program. Later, if you want to try launching any of the other modules, you will need to do this as well.


  • Select your Android device or emulator and click OK. This will install the watch face on the Wear OS device or emulator.
  • After a couple of seconds, your watch face is built and ready to deploy. You will see a spinner in the status bar at the bottom of Android Studio while this is happening:


  • If it is not already at the "4: Run" tab at the bottom left hand side of Android Studio, select that tab and you can see the installation progress. At the end of the installation process, you should see something similar to this:
Waiting for device.
Target device: lge-urbane_2-XXXXXXXXXXXXXX
Uploading file
        local path: ~/Downloads/watchface/1-base/build/outputs/apk/1-base-debug.apk
        remote path: /data/local/tmp/
DEVICE SHELL COMMAND: pm install -r "/data/local/tmp/"
pkg: /data/local/tmp/
  • Once that has happened, press the back (triangle) button on the emulator to wake the watch
  • Long press or click &" hold on the watch face of your device or emulator.
  • Swipe left and tap "See more watch faces"
  • Scroll until you see a watch face labelled "Analog Codelab Watchface", select it. 4e3641f573f61c71.png
  • If you do not see this, try deploying the watch face again by pressing the green triangle button in the toolbar.

Here's what it should look like. Don't worry if your emulator has a cloud with a strikethrough in place of the aeroplane icon. We will not need connection to a phone / internet for this code lab. Also note that the power button to the right might not appear - this is okay!


Additional background information - not necessary for code lab

Watch face templates are available in Android Studio and make it really simple to add watch faces to an existing application. To add watch faces to an existing project:

  • Open your existing project
  • If it does not have an Wear OS module, add one by selecting, File > New > New Module. Then select "Wear OS module". Fill in the module name, click next.
  • Go to the Wear OS module, right click on the folder named "java". Select New > Wear > Watch Face.
  • Go through the wizard to add either an analog or digital watch face.

The resulting project will be very similar to "1-base" module in this code lab.


In this step you've learned about:

  • Wear OS and the concepts behind watch faces
  • The basics of our starting point - 1-base
  • How to connect to Wear OS device, deploy the watch face and run it!

Next up

Let's start making this watch face our own by changing the background.

2. Change the background

In this step, we will start making the watch face our own by giving it a background. If at any point you are confused by the concepts discussed here, please refer to the 2-background module and see how these steps may be implemented.

Prepare your image

The first step is to prepare the image. You can select any photograph of your choice, but note that some images with tiny details may not scale well on a small watch display. Crop it to a square shape and resize it to something like 600 x 600 pixels. It can be in JPEG or PNG format. The next step is to rename it to custom_background.jpg or custom_background.png (Android needs underscore in place of 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-nodpi.

If you do not have an image, go to res/drawable-nodpi directory under 2-background - copy the custom_background.jpg image to your res/drawable-nodpi under 1-base.

Create Bitmap and Paint objects

Before we can display the bitmap, we need to load and instantiate the object. Since we only want to do this once and we don't need the dimension of the screen, we can put this into the onCreate method.

Let's change the files in the 1-base module:

  • Create a private Bitmap variable mBackgroundBitmap in the MyWatchFaceService.Engine class. This enables other methods to get hold of the Bitmap to resize it and draw later.
  • In the onCreate method in MyWatchFaceService.Engine class, we will instantiate the bitmap:
  • Load the background bitmap:
mBackgroundBitmap = BitmapFactory
    .decodeResource(getResources(), R.drawable.custom_background);

Resize the Bitmap object

Next we are going to resize the background bitmap. Since dimensions are not available in onCreate, we resize the Bitmap in onSurfaceChanged:

  • In onSurfaceChanged method, add code to resize the Bitmap object using the width of the screen (the third parameter of the onSurfaceChanged method) and the width of the background bitmap:
mScale = ((float) width) / (float) mBackgroundBitmap.getWidth();
  • Scale the background bitmap:
mBackgroundBitmap = Bitmap.createScaledBitmap
    (mBackgroundBitmap, (int)(mBackgroundBitmap.getWidth() * mScale),
    (int)(mBackgroundBitmap.getHeight() * mScale), true);

Draw the background

Now that the bitmap is correctly sized - let's draw it!

  • Delete the drawRect code in onDraw which draws a black square which wipes the frame clean.
  • Add code to draw the background bitmap in onDraw. We suggest you place this code directly below the code we deleted in the last step.
canvas.drawBitmap(mBackgroundBitmap, 0, 0, mBackgroundPaint);

Run the watch face again

In the first step, you learned how to install the watch face to your device or emulator. Now it's time to do that again! Your watch face should look something like this:



In this step you've learned about:

  • Loading a bitmap object
  • Resizing it based on the screen dimensions
  • Drawing it on the screen!

Next up

Let's refine the watch arms!

3. Change the Watch Hands

Code step 3

While the current watch hands get the job done, we want to give the watch hands a more premium makeover. In this section, you will learn more about drawing on Android canvas.

Prepare the paint objects

Before an artist starts, they need to mix their color palette and ready their brush. This is what we will be doing:

  • Define a private static final float constant HAND_END_CAP_RADIUS within MyWatchFaceService.Engine and set it to 4. Remember to put an "f" after the 4 to indicate that this is a float rather than an integer.
  • Define a private static final float constant SHADOW_RADIUS under MyWatchFaceService.Engine and set it to 6. Remember the "f"
  • Change the mHandPaint object with the following parameters in onCreate:
  • setShadowLayer with the following parameters:
  • radius: SHADOW_RADIUS
  • x offset: 0
  • y offset: 0
  • color: Color.BLACK
  • setStyle to Paint.Style.STROKE - this means we can draw an outline of shapes

Calculate the length of the watch hands

Different watches may have different size screens. Next to scaling the background, as we did in the last step, we also need to work out the watch hand lengths. Since screen dimensions do not change, we can insert the calculation code into the method onSurfaceChanged:

  • set hour hand length to be 0.5 * width / 2
  • set minute hand length to be 0.7 * width / 2
  • set second hand length to be 0.9 * width / 2

Draw the watch hands

Now that all the length calculation is done, it's time to draw the watch hands. In this section, we will walk you through the code to rotate the watch hands using canvas.rotate rather than using sine and cosine. This simplifies the code tremendously reducing the chance for error, allows more complex layouts as we will see later and leaves the optimisation to Android.

First of all we will prepare the canvas for the first hand we draw - the hour hand. So in the onDraw method:

  • Remove the code which draws the current watch hands (simple lines) using canvas.drawLine() from the line to canvas.restore(). We will step you through putting in the new watch hand code in the following steps.
  • Save the current rotational state of the canvas:;
  • Rotate to draw the hour hand
canvas.rotate(hoursRotation, mCenterX, mCenterY);

The rotate command above means that we have rotated the canvas counter-clockwise by the desired amount. This means we can just draw the hour hand in an upright direction rather than at an angle.

In addition, for our hour hand, instead of a line, we want to draw a hollow paper clip like shape for our watch hands. Before we begin, we need to think a little bit about our design:

  • Hollow paper clip - It's basically a rectangle with two ends where it's completely round. For our design we have chosen 4px being the radius of the round corners:


  • Next is to think about the offset that we have to put in order for the watch hands to be centered correctly. Without this the watch hands will be centered to the bottom of the whole object rather than the center of the bottom round end. It should come as no surprise that this offset is equal to the radius. In our case, this will be 4 px.


To draw the watch hands:

  • Since we need to draw the hour hand and the minute hand in the same way, we create a new private method drawHand. This will help us only deal with the drawRoundRect code once. If there are any mistakes, we can fix it in one place rather than two. For this method we need both the canvas and the length of the hand:
private void drawHand(Canvas canvas, float handLength) {
    canvas.drawRoundRect(mCenterX - HAND_END_CAP_RADIUS,
        mCenterY - handLength, mCenterX + HAND_END_CAP_RADIUS,
        HAND_END_CAP_RADIUS, mHandPaint);
  • Back to the onDraw method, we draw the hour hand:
drawHand(canvas, mHourHandLength);
  • Next, we rotate the canvas to draw the minute hand, taking into account of the rotation of the hour hand drawn before.
canvas.rotate(minutesRotation - hoursRotation, mCenterX, mCenterY);
drawHand(canvas, mMinuteHandLength);
  • Draw the minute hand in a similar way to how we draw the hour hand. Remember to feed in the correct hand length
  • Rotate to draw the second hand, taking into account of the rotation of the minute hand. Do not worry about the rotation that we made for the minute hand. Remember the bit where we rotate minus the minuteRotation, with that we have "neutralised" the minute hand rotation and all we need to do in this step is to "neutralise" the hour hand rotation. Lastly, do not worry about the ambient mode code. We will add that in the next section.
  • Draw the second hand in the center of the screen adjusting for the radius of the hour and minute watch hand. This means there should be a circular area in the center which is transparent:
canvas.drawLine(mCenterX, mCenterY - HAND_END_CAP_RADIUS, mCenterX,
    mCenterY - mSecondHandLength, mHandPaint);
  • Restore the canvas to upright position:

How to check your progress and debug

If you run the watch face now, you should see something like this:


Check that:

  • The time is accurate - if you are using the emulator and this is not paired with the phone, the time can be different to the time of your laptop. Check the watch face against another watch face or the time that is shown in the log window in Android Studio. If the logging does not appear, try checking four things:
  • At the bottom left, the tab "6: Android" is selected.
  • Under devices, the correct device is selected. In the example below, it is "Emulator Android_Wear_Round_API_23".
  • The "Log level" is set to "Verbose".
  • If nothing shows up, select "No Filters".


  • The second hand is moving and the minute hand increments at the 60 seconds mark

It is easy to make mistakes in calculating the rotation angle or setting the center of rotation. If these look odd consider logging these variables and checking the calculation by using

Log.d("MyWatchFaceService", "variable_you_want_to_log: " + variable_you_want_to_log);

and checking that the value makes sense. For primitives such as int or float, these can be logged directly as shown. For objects such as mCalendar, you will need to log its String representation by logging mCalendar.toString() rather than logging mCalendar. Otherwise,the code will not compile as the method is looking for a String object rather than a Calendar object.

Before publishing your watch face, we recommend that developers test their design in their daily lives and see that it both works correctly technically and that the design works in all circumstances (indoor / outdoor / stationary / on-the-move).

Perfect the center

Coming back to the current design, you might notice that at the center the shadow of the second hand is on top of the hour hand, and it looks a little out of place. A solution is to add a hollow circle in the middle above the second hand to solve this:

canvas.drawCircle(mCenterX, mCenterY, HAND_END_CAP_RADIUS, 

If you run the watch face again, it should look something like this:


Change the preview image in the watch face selector

In the watch face selector, you can see a preview of the watch face. This can be changed by replacing the preview image - preview_analog.png in the res/drawable-nodpi directory.


In this step you've learned about:

  • Setting up paint objects to draw hollow shapes
  • Rotating watch arms into the correct position
  • Drawing rounded rectangle shapes.

Next up

In addition to interactive mode, Wear OS watches also have an ambient mode which normally has a more discreet design and is only updated once a minute. In the next section, we will learn about how to deal with this.

4. Account for ambient mode

Code step 4

Aside from the interactive mode, Wear OS also has an ambient mode. Ambient mode helps the device conserve power. We typically recommend developers use black, white, and grays in this mode. Developers may also use limited color but the design should clearly signal that the watch is in ambient mode.

Aside from color differences, another way that ambient mode is different is that the watch face will only be updated once a minute. As a result, screen elements which update more often such as animation or seconds hand should be removed in this mode.

React to ambient mode

Within the MyWatchFace.Engine class, there is a method called onAmbientModeChanged. This method will be called when the watch is going into or out of ambient mode. This gives you a chance to change the design.

For our watch face, we will do three things to the watch face if it does go into ambient mode:

  1. Change the background to be grayscale
  2. Remove anti-aliasing of the watch hand paints
  3. Remove the seconds hand

For 1, we can do this by creating a copy of the bitmap and apply a grayscale filter to it:

  • Create a new Bitmap object called mGrayBackgroundBitmap in MyWatchFaceService.Engine.
  • Make a copy of the background bitmap and apply a grayscale filter to it. We recommend doing this in a separate method for clarity sake. We will invoke this new method initGrayBackgroundBitmap() at the end of the method onSurfaceChanged. The method should do the following:
private void initGrayBackgroundBitmap() {
    mGrayBackgroundBitmap = Bitmap.createBitmap(
        mBackgroundBitmap.getHeight(), Bitmap.Config.ARGB_8888);
    Canvas canvas = new Canvas(mGrayBackgroundBitmap);
    Paint grayPaint = new Paint();
    ColorMatrix colorMatrix = new ColorMatrix();
    ColorMatrixColorFilter filter = new 
    canvas.drawBitmap(mBackgroundBitmap, 0, 0, grayPaint);
  • In onDraw, replace the background image draw code with the following which takes into account of ambient modes:
if (mAmbient) {
    canvas.drawBitmap(mGrayBackgroundBitmap, 0, 0, mBackgroundPaint);
} else {
    canvas.drawBitmap(mBackgroundBitmap, 0, 0, mBackgroundPaint);

For 2, we add the following code into onAmbientModeChanged to switch anti-aliasing on and off.

mAmbient = inAmbientMode;

if (inAmbientMode) {
} else {


For 3, we update the code in onDraw to put a condition to check if mAmbient is false around the code that rotates and draw the seconds hand. This ensures that the seconds hand is only drawn in interactive mode. This is because the watch face is usually only updated once a minute in ambient mode.

Run the watch face. If you have an emulator, press F7 to toggle between interactive and ambient mode on your keyboard. If you have a physical device, cover the display with your hand. You should see that your watch face looks something like this:


Account for special screens

In additional to LCD screens, some Wear OS watches support:

  • low bit mode - where pixels can only be switched on or off. Since each pixel consists of red, green and blue, it is possible to create some color in this mode but it will be very basic and may not look its best. We recommend developers think about black and white images which may work, or switch off the background altogether.
  • burn-in protection mode - some screens such as OLED suffer burn in if the same image is displayed constantly. As a result, we recommend that no more than 5% of the screen should be lit in ambient mode for these watches. Any solid filled areas should be hollowed out. Lastly, for analog watch faces, the center of the watch arms should be hollow so as not to burn in the center pixels.

To keep things simple, we will switch off the background if either of these modes are detected:

  • We will create two boolean variables in MyWatchFaceService.Engine to keep tab of: 1) the low-bit screen mode: mLowBitAmbient and 2) the burn-in protection screen mode: mBurnInProtection.
  • Add and override the method onPropertiesChanged in MyWatchFaceService.Engine like this:
public void onPropertiesChanged(Bundle properties) {
    mLowBitAmbient = properties.getBoolean(
    mBurnInProtection = properties.getBoolean(
  • Replace the background drawBitmap code in onDraw to the following conditional code which only draw the background if these two modes are not detected in ambient mode:
if ((mAmbient && mLowBitAmbient) || (mAmbient && mBurnInProtection)){
} else if (mAmbient) {
    canvas.drawBitmap(mGrayBackgroundBitmap, 0, 0, mBackgroundPaint);
} else {
    canvas.drawBitmap(mBackgroundBitmap, 0, 0, mBackgroundPaint);
  • Also as a refinement to earlier code, we can put a condition into the onSurfaceChanged() method to only create the grayscale bitmap if the watch is not in low bit or burn in protection mode:
if (!mBurnInProtection || !mLowBitAmbient) {

If you run this code on a supported device (e.g. Sony Smartwatch 3 for low-bit ambient mode and LG Watch Urbane 2nd Edition for burn-in protection mode), it should look like the following picture. For the purpose of this code lab, it is okay not to test this. For production, we recommend that you test against devices with these different screens.



In this step you've learned about:

  • Taking ambient mode into account
  • Building watch faces for special screens

Next up

An optional activity to learn about how we can add automatic color selection into our code, so that the watch hand color will automatically work with the background.

If you still have time but don't fancy having a go at the palette API, we encourage you to alter the different parameters of the screen elements, for example, stroke size, the radius of the watch arms, color of the various screen element, etc. Let's see what you get!

5. Automatic color selection using Palette API

Code step 5

The Palette API helps automatically select the accent color of a bitmap. We will be using this API for automatically selecting the color of the watch hands. Outside of watch faces, you can use it to generate dynamic color schemes based on the user's input and fulfil one of the creative visions of material design.

Determine key colors of a bitmap

We will need to initiate the Palette object, feed our background bitmap to it and get it to analyse the result:

  • Open "build.gradle (Module: 1-base)" file under Gradle Scripts: d5306d6da65aae27.jpeg
  • Add the following to the dependencies section towards the end of the "build.gradle (Module: 1-base)" file:
compile ''
  • Press blue "Sync Now" at the top - this will trigger a rebuild and palette will be available for use.


  • Create two int variables, mWatchHandColor and mWatchHandShadowColor, in MyWatchFaceService.Engine to store the colors. Initiate them with Color.WHITE and Color.BLACK respectively.
  • Instantiate a Palette in onCreate after the mBackgroundBitmap has been loaded:
    new Palette.PaletteAsyncListener() {
      public void onGenerated(Palette palette) {
        if (palette != null) {
          Log.d("onGenerated", palette.toString());
          mWatchHandColor = palette.getVibrantColor(Color.WHITE);
          mWatchHandShadowColor = 
  • Add a new private method in MyWatchFaceService.Engine to set the color of the watch hands
private void setWatchHandColor(){
    if (mAmbient){
        mHandPaint.setShadowLayer(SHADOW_RADIUS, 0, 0, Color.BLACK);
    } else {
        mHandPaint.setShadowLayer(SHADOW_RADIUS, 0, 0, mWatchHandShadowColor);
  • Call the setWatchHandColor() method before invalidating the frame in onAmbientModeChanged

Run the watch face again

Your watch face should look something like this:


If you copy over the custom_background2 image from the module "5-palette" to "1-base" and change the backgroundResId to custom_background2, you should see a watch face similar to this:



In this step you've learned about:

  • How to select color schemes automatically using the Palette API
  • Setting the screen elements color accordingly

6. Next Steps

For more details about developing Wear OS notification and apps:

Here are some of the common customisation steps for watch faces:

Positioning status icons, the charging icon (the lighting bolt), "Ok Google", etc.

Refer to the WatchFaceStyle.Builder documentation for various options from setting gravity to making a semi-transparent background so that they are readable against the watch face.

Putting the watch face on the Google Play Store

What about digital watch faces?

Use the Wear OS watch face template in Android Studio. This will help you get the skeleton code:

  • Start a new project or open your existing project
  • Create a new Wear OS module with no activity if your project does not already have it.
  • Right-click on the module name on the left hand side. Select New > Wear > Watch Face


  • Select the digital watch template.

Learn More

Watch these great videos:

Take the Ubiquitous Computing Online course