4.1 Starting a Digital Watch Face
Watch faces are the easiest way for users to customize their Android Wear experience. This lesson will introduce you to developing watch faces and help you get one set up on a device.
1.Introduction and Getting Set Up3 lessons, 11:45
2.Wearable App UI Components6 lessons, 1:15:54
3.Wearable Notifications4 lessons, 38:35
4.Creating a Watch Face2 lessons, 34:28
5.Conclusion1 lesson, 02:14
4.1 Starting a Digital Watch Face
Hey, everyone and welcome back to developing for AndroidWear. This is Paul with Techs Plus. And in this lesson, we will start looking at how to make a custom watch face. So, the way the custom watch faces work is there's actually a WatchFaceService that will fun on the watch and the system will know how to interact with that so that it can draw your watch face for your users. So, we'll be using an extension of the watch face service called CanvasWatchFaceService. However, there is a GLES2WatchFaceService that is specifically made so that it can work with OpenGL for rendering everything. But since we're going to keep this fairly simple, what we'll use is the CanvasWatchFaceService Which provides a canvas that you can draw on so that it can draw out your watch face. So, let's go ahead and actually look at the documentation for the Watch Face Service, which is the parent of this class. And the documentation here will actually have a little bit of information on some of the methods involved, in particular this thing called the wallpaper service dot engine. And we'll actually implement our own engine within our Canvas Watch Face Service. But if you scroll down a little bit more, you can get some information on things that need to be added to your application so that you can get set up and running with the initial watch face. And we're going to do that right now. So let's go back to android studio. And we're going to go into where, source, main, java, and our package. And let's go ahead and create a new package called services which is where we will house our watch face service. So, I've got a new, and then down to package. Let's call this services. And then within services, let's right click and create a new Java class, and we'll call this digital watch face service. And let's go ahead and extend the canvas watch face service. Now, there's one method within this wanted to overwrite, which is called encre engine. And within this we need to create an inner class, called an engine, that extends CanvasWatchFaceService.Engine. So let's go ahead and use private class engine extends CanvasWatchFaceService.Engine. And within onCreateEngine we'll just go ahead and return a new engine. Now that we have a sub for our service, let's go ahead and go to AndroidManifest.xml. And we'll create a node for our service here. So, within the application node, let's create a couple new lines here. And we'll say Service. And we'll set the name to services.DigitalWatchFaceService. And then within that, we need to add in a label, which is how the watch face will show up on our watch face selector. So, let's go ahead and use android:label is equal to. And let's call this TutsPlus Watch Face. And then we need to add a new line which is gonna add an extra permission for bind wallpaper. So, Android; permission and this is Android.permission.bind_WALLPAPER in all caps for the last part. And then we can go ahead and close this off with our bracket and if we go back to our documentation.- We can actually see that there's some metadata that we need to add. So let's go ahead and just copy this metadata. And we'll go back to Android Studio, and we'll paste that in. And since we don't have a preview for a square or a round watch face, we're gonna go ahead and just switch this over to the IC launcher. We'll say IC launcher And since this isn't in the drawable folder, we'll go ahead and switch this over to be a mitmap. And we'll copy this, because we're going to use the same exact thing for the rom devices. And something that's not mentioned in the documentation for The watch face service is one more piece of metadata that is used to actually let the system know that this service can be used as a watch face. So if we go back to Android Studio, we'll need to go under the folder. And let's create a new folder. So I'll go to New, Android resource directory. And we'll call this xml. And then we need to create a new resource file within this. So, we go to New XML resource file. And we'll call this watch_face. And rather than this being a preference screen, it'll actually be a wallpaper. So we'll just type in wallpaper, all in lower case. We'll leave the XML ns. So, we can save and close this. And, then, back in our manifest, we can come down to the metadata section, and we'll add a new metadata item. So, meta-data, name is equal to android.service.wallpaper And then we need to point to the resource file that we just created, so this will be resource is equal to at xml/watch_face and then we can close this off. And if we go back to the documentation for the watch face service you'll notice that there's also an intent filter so let's go ahead and copy that and we'll just place this within the service node. And with that we should be all done with android manifest, so let's go ahead and save and close that. And now we can start flushing out our actual wash face service. So, pretty much everything is done for the on create engine part and the actual service, but the engine here is what drives everything So for this watchface all we're gonna do is display the time as a set up text so that your users can just read the time. So in order to do that we need to actually set up text for this canvas so that it can be painted on to the screen. So, if we go down to the engine, let's go ahead and create a typeface first. So I'll say private, typeface. It'll say WATCH_TEXT_TYPEFACE = Typeface.create and we're gonna use the Typeface.SERIF type and we'll also use Typeface.NORMAL. So this will be the font that's used to display our text We also need to create a couple more items that'll be used throughout this class. The first set will be private paint and background color paint, which is what we'll use to draw out the background of this. And in this case we're just gonna use a solid color. Next, we'll also need to create a paint for the text. So use private paint M text color paint. Once we have the paint, let's also go ahead and define the colors so use private int M background color which is what we'll use to initialize our paint and we'll say it's equal to color dot parse color and we'll pass on the color of white. So that we have a white background. And it will also use private int mTextColor is equal to Color.parseColor. And we'll say it's going to be red. So, we have red text on a white background. We'll go ahead and import color. And then finally, we will need to have a time object, so we know what to display. So we'll say private time end time. And we get import time, let's make sure that it is the android text format time. And now we get started defining some of our methods. So let's go ahead and create on create. We'll also need to have on time tick, which is called every minute and this is what we will use to update whatever is displayed. And then since this service does use a canvas, we'll need to have an on draw method. And then later on, we're gonna have some helper methods that we will use to actually get these things working together correctly. Okay, now that we have our stubs done, let's go ahead and go back into on create, and the first thing we're gonna use is setWatchFaceStyle. And this is going to consist of a new WatchFaceStyle.builder. And we need to pass a context to it. So since this is an inner class, we can use digitalWatchFaceService.this. And that'll pass the context of the parent class. And if you want to see what kind of methods we can use with this builder, we can actually go back to the documentation site And we can look up the WatchFaceStyle, which itself has some values that we will use. So if you want to look at this you can see what those values represent. But we're going to go over to the side here and we're gonna go to WatchFaceStyle.Builder so you can see what kind of properties can be set as the defaults for your watch face. The properties that we will use for this course will be setback prime visibility, set card peak mode, and set show system UI time. So if you want to scroll through the watch face style.buildersite, you can actually see what those methods will do, and how they'll affect your watch face when your using is using them. So let's go back to Android studio and on our builder let's go ahead and add a new line. We'll say dot set background visibility, and we'll use watch face style dot background visible interruptive. Then we'll add on another line, and this one will be set card peak mode. And this will have WatchfaceStyle.PEEK_MODE_VARIABLE. After that, we're going to want to set our system time to not show up. So we'll use .setShowSystemUiTime to false. And the reason that you're gonna do that is because you will display the time yourself, so you don't need the system to display its default values. So, once we set those properties we can go ahead and just say .build. And the setWatchfaceStyle method will be all set. Next, let's go ahead and initialize our paints. And you will want to do these in onCreate, simply so they're not being done in onTimeTick or onDraw, because they do take a fair amount of time relatively speaking. So, it's best to not do these 60 times a second. So, what we're going to do is say nBackgroundColorPaint is equal to a new paint object. And then nBackgroundColorPaint.setColor to nBackgroundColor. Once our background color has been initialized, we can go ahead and set up our text. So, we'll say nTextColorPaint, Is equal to a new paint object, and then mtextcolorpaint.setcolor and we're gonna set this to mTextcolor and then we need to set up the actual font for this. So in order to do that we're gonna use mTextColorPaint.setTypeface as our watch text typeface. And then, we're going to need to set a text size. So in order to do this, we'll actually need to have a dimensions file with the text size stored within it. So let's go ahead and go back to our res folder and enter values, we're gonna go ahead and right click and go to new, values resource file, and we will just call this Dimens. And within that we need to add one dimension. So we'll use dimen, name is equal to, watch face text size and let's go ahead and use 50 SP. Once we have that, we can go ahead and close the dimens file and then we'll set our text size. So we'll use M text color paint.- .setTextSize. getResources.getDimensions. R.dimen.watch_face_text_size. And let's go ahead and import R. And finally we will need to use m text color paint dot set anti alias to true which will help us when we are actually drawing out everything and it essentially just helps with the efficiency so once we have our text color paint initialized we can use m time is equal to new time. And this will be the time object that we will use for determining what we will display to our users. Next, we can scroll down to on time tick, and within this method, all we will do is call invalidate. So when the time ticks, and this system method is called, we'll invalidate our canvas so that on draw can be called. And then we can display whatever the new time is. So if we scroll down to onDraw now, what we're gonna do is use nTime.setToNow so that we can get the current time and then let's draw our background as a draw rect over the entire screen. That's done by calling canvas.drawRect Zero, zero which is the upper left corner and then we're gonna use bounds.width to cover up the entire width of the screen. And then bounds.height to get the entire height of the screen and then we need to pass in the paint that we're gonna use to color in that section. So we'll use mbackgroundcolorpaint. Next, we need to draw our our actual text for the time. So in order to do this, let's kit a new string for time, we'll call it time text, is equal to mTime.hour plus colon plus string.format, and we'll use %02d, so that we only get two digits from our minute, even if the time is set to Six minutes after the hour we'll end up with 06. And then we need to pass in the actual minute. So nTime.minute. And something to be aware of here is that time.hour is actually a 0 to 23 Three value. So let's go ahead and replace mTime.hour with a helper method to give us 1 through 12. So let's create a new method underneath on draw, private String getHourString and if( mTime.hour % 12 == 0 ) Now we'll return the text of 12 else if m time.hour is less than or equal to 12 then we can just go ahead and return string.value of m time.hour. So this will give us one through 12. So if we're actually in the AM portion of time. We will end up with either 1 through 12 as the return value and else we will return string.valueof mTime.hour minus 12. So we end up with the format of our time even if we're in the PM part of the day. So let's just go ahead and throw in our last semicolon here. And then we need to append AM or PM to this. So lets say timeText += we'll use a parenthesis here mTime.hour Question mark, AM, otherwise colon for PM. This way, we can just use a operator to append AM or PM to our time text. And then we need to actually draw this text onto our canvas. And we do that by calling canvas.drawText, And we'll just pass in our text. We need to tell it what our offsets will be from the left and the top, and in this case, you can actually add different values for round or square faces with another method, which we'll get into in the next lesson, but for now, let's just go ahead and say 75 and 150, which'll push this fairly close to the right and almost halfway down. And then we need to pass in our paint. So m text color paint. Once we have that we can go ahead and install our application onto a wearable device. And we can go ahead and hit OK. We'll go to our emulator. We can go ahead and close this application. And what we're gonna do to select the watch face is we hold down on the watch face and the system will present us with a watch face selector. So let's go ahead and scroll over and the watch face that we'll want is TutsPlus without the plus sign. That was another application that I was working on. So we can click on that, and you'll see that we now have our application here. It looks like we did lose the M off the side here. So my guess is we probably just need to set the padding back a little bit. So instead of using 75, we can set this to probably a good 40 or so should work. So we'll do that. But for now, that's pretty much it, we have our watch face set up, and you can see the actual text and when the time changes like it just did the watch face will automatically update. So in the next lesson We'll start adding in a couple different methods that are part of the watch face service. They add support for changing time zones, entering ambient modes, and handling the visibility change from when your user puts their hand down and the watch goes dark and then coming back up. So I will see you then.