Garmin Watch Face Creator

Step 1: Open your Fitbit app, go to your watch (tap on the little watch thumbnail on the top left) and tap on 'Clock Faces'. Step 2: Scroll down to the 'RATE THIS ITEM'-section. Step 3: Tap on the very last star on the right (or further to the left if you want to rate less than 5 stars). Step 4: All done! 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 - previewanalog.png in the res/drawable-nodpi directory. In this step you've learned about. From the watch face, hold the touchscreen. Select Watch Face. To customize an existing watch face, select the watch face, and select Customize. To create a new watch face, swipe to the bottom of the watch face list, and select Create New. Swipe up or down to scroll through the analog and digital dials, and tap the screen to select the displayed. My wife wanted a Mickey Mouse watch face. The outer red ring animates based on step goal percentage and the blue ring for floor goal percentage. Top fields are heart rate (red) and steps (black). Unfortunately I can't publish it to the app store due to the obviously copyrighted content but it was still fun to make. Connect IQ watch face settings can be adjusted in two ways: 1. Directly on the watch, if the watch and the app allows it. To do this, first you need to get to the watch face selection menu on your watch. When you are there and your face of choice is being shown, you will always be presented with the “Apply” option.

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.

Create garmin 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.

git --version in the terminal / command line and verify it executes correctly.)

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

Face

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.)

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'.

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/com.android.example.watchface.
  • 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!

To achieve a high frame rate, which results in smooth animations, no intense computations should happen in onDraw. We can load images and resize them before we start drawing in onCreate and onSurfaceChanged.

  • res/drawable-nodpi/ - This is the directory where we will be placing some additional image files.
Garmin Watch Face Creator

  • 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).

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'.

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:
  • 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.
  • 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!

Garmin Watch Face Creator App

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.

  • 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!

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.

custom_background.jpg orcustom_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.

We will need to import additional classes from Android framework / Java packages to help us throughout this code lab. As you type out class names like Bitmap, Android Studio will display a drop down list. Using the up and down arrow keys, you can select the class that you are meaning to type (see below).

When you get to the correct one and press enter, Android Studio will autocomplete the name for you as well as adding an import line at the top of the file which brings the functionality of that class into use.

If you missed this, don't worry. The class name will be underlined in red if the import statement is not added. At this point, you can take the cursor back to that class name and press Alt-Enter and the import will be magically inserted.

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:

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:
  • Scale the background bitmap:

  • 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.

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

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

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

Remember to put 'f' after the decimal number of 0.5, 0.7 and 0.9 or Java will complain that these are doubles rather than floats and refuse to compile.

Why do we set the length to be a proportion of the screen rather than half the width minus some fixed number? Proportion scales better for different size screens. Wear OS already has a number of different devices and more will come. This will make it more future proof.

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 canvas.save() 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

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:
  • Back to the onDraw method, we draw the hour hand:
  • Next, we rotate the canvas to draw the minute hand, taking into account of the rotation of the hour hand drawn before.
  • 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:
  • Restore the canvas to upright position:

  • 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

    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).

    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.

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

    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.

    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

    Anti-aliasing is a technique which helps smooth out the edges of the shape that is being drawn. In ambient mode, we want to reduce the amount of processing done. As a result, we switch this off.

    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:
    • In onDraw, replace the background image draw code with the following which takes into account of ambient modes:

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

    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:

    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:
  • Face
    • 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:
    • 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 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.

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

    Garmin Face It Watch Face Creator

    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!

  • Add the following to the dependencies section towards the end of the 'build.gradle (Module: 1-base)' file:
  • How Do I Download Watch Faces To My Garmin

    • 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:
    • Add a new private method in MyWatchFaceService.Engine to set the color of the watch hands
    • Call the setWatchHandColor() method before invalidating the frame in onAmbientModeChanged

    backgroundResId to custom_background2, you should see a watch face similar to this:

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

    For more details about developing Wear OS notification and apps:

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

    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.

  • Second, package the watch face with a mobile app.
  • Third, upload to the Play Store.
  • The permissions required for the watch face will need to be copied over to the mobile app.

    Learn More

    Watch these great videos:

    Face

    Take the Ubiquitous Computing Online course