{"data":{"site":{"siteMetadata":{"title":"IJHDev Blog","author":"Ian Hayward"}},"markdownRemark":{"id":"aea9da0a-4ee0-5a68-a1f2-a2175ead476e","html":"<p>Making a wearOS watch face and avoiding some of the faff. (TurtleWare 2.0 pt2)</p>\n<!-- end -->\n<p>This is part 2 of a 3 part blog post about making v2 of turtle wear watch face. <a href=\"https://ijh.dev/middlewear-go\">You can check out part 1 here</a></p>\n<h3>Starting the project off</h3>\n<p><img src=\"./images/trtlwear.jpeg\" alt=\"Watch\"></p>\n<p>Starting off, WearOS is the same as Android for 99% of things. Meaning you can write the app Kotlin (or Java if you love some boilerplate) and use all the same Android libraries. So for folder structures and initializing the project can be done in Android Studio just like you would a phone app. For Turtle Wear 2.0, there are two important entry points. The CanvasWatchFaceService and the MainActivity.</p>\n<h4>CanvasWatchFaceService</h4>\n<p>The CanvasWatchFaceService is the place where you run all the watch face visuals. You set an inner class that contains a CanvasWatchFaceService.Engine() which deals with refresh speeds, ambient and active visuals, and custom tap commands. The CanvasWatchFaceService is pretty standard and should look something like the below:</p>\n<div class=\"gatsby-highlight\" data-language=\"java\"><pre class=\"language-java\"><code class=\"language-java\"><span class=\"token keyword\">class</span> <span class=\"token class-name\">TurtleFace</span> <span class=\"token operator\">:</span> <span class=\"token function\">CanvasWatchFaceService</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">{</span>\n\n  var specW<span class=\"token operator\">:</span> Int <span class=\"token operator\">=</span> <span class=\"token number\">0</span>\n  var specH<span class=\"token operator\">:</span> Int <span class=\"token operator\">=</span> <span class=\"token number\">0</span>\n  <span class=\"token keyword\">private</span> val displaySize <span class=\"token operator\">=</span> <span class=\"token function\">Point</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span>\n\n  companion object <span class=\"token punctuation\">{</span>\n    <span class=\"token keyword\">private</span> <span class=\"token keyword\">const</span> val INTERACTIVE_UPDATE_RATE_MS <span class=\"token operator\">=</span> <span class=\"token number\">1000</span>\n    <span class=\"token keyword\">private</span> <span class=\"token keyword\">const</span> val MSG_UPDATE_TIME <span class=\"token operator\">=</span> <span class=\"token number\">0</span>\n  <span class=\"token punctuation\">}</span>\n\n  override fun <span class=\"token function\">onCreateEngine</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token operator\">:</span> Engine <span class=\"token punctuation\">{</span>\n    <span class=\"token keyword\">return</span> <span class=\"token function\">Engine</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span>\n  <span class=\"token punctuation\">}</span>\n\n  <span class=\"token keyword\">private</span> <span class=\"token keyword\">class</span> <span class=\"token class-name\">EngineHandler</span><span class=\"token punctuation\">(</span>reference<span class=\"token operator\">:</span> Engine<span class=\"token punctuation\">)</span> <span class=\"token operator\">:</span> <span class=\"token function\">Handler</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">{</span>\n    <span class=\"token keyword\">private</span> val mWeakReference<span class=\"token operator\">:</span> WeakReference<span class=\"token generics function\"><span class=\"token punctuation\">&lt;</span>Engine<span class=\"token punctuation\">></span></span> <span class=\"token operator\">=</span> <span class=\"token function\">WeakReference</span><span class=\"token punctuation\">(</span>reference<span class=\"token punctuation\">)</span>\n\n    override fun <span class=\"token function\">handleMessage</span><span class=\"token punctuation\">(</span>msg<span class=\"token operator\">:</span> Message<span class=\"token punctuation\">)</span> <span class=\"token punctuation\">{</span>\n      val engine <span class=\"token operator\">=</span> mWeakReference<span class=\"token punctuation\">.</span><span class=\"token function\">get</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span>\n      <span class=\"token keyword\">if</span> <span class=\"token punctuation\">(</span>engine <span class=\"token operator\">!=</span> null<span class=\"token punctuation\">)</span> <span class=\"token punctuation\">{</span>\n        when <span class=\"token punctuation\">(</span>msg<span class=\"token punctuation\">.</span>what<span class=\"token punctuation\">)</span> <span class=\"token punctuation\">{</span>\n          MSG_UPDATE_TIME <span class=\"token operator\">-</span><span class=\"token operator\">></span> engine<span class=\"token punctuation\">.</span><span class=\"token function\">handleUpdateTimeMessage</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span>\n        <span class=\"token punctuation\">}</span>\n      <span class=\"token punctuation\">}</span>\n    <span class=\"token punctuation\">}</span>\n  <span class=\"token punctuation\">}</span></code></pre></div>\n<p>The inner class Engine has a lot more moving parts, but some bits to consider are:</p>\n<ul>\n<li><strong>Standard Android lifecycle events</strong> - So you can deal with the watch face starting, going into the background and being stopped when changed</li>\n<li><strong>onAmbientModeChanged</strong> - This is where you can control what you show and hide when the user is actively looking at the watch or not.</li>\n<li><strong>onTapCommand</strong> - This controls any custom action you want your watch face to perform, like a double tap to refresh the view</li>\n<li><strong>onDraw</strong> - The main visuals for your view go here rather than OnCreate</li>\n<li><strong>onApplyWindowInsets</strong> - This helps with different screen sizes (Round, flat tire, square) so your watch face fits all of them</li>\n</ul>\n<h4>MainActivity</h4>\n<p>This should be familiar to anyone who has made an Android app, this is where your android.intent.action.MAIN and android.intent.category.LAUNCHER is set to on the manifest. In this case, it will be the launch point for the settings app.</p>\n<h3>Setting up the simulator</h3>\n<p><img src=\"./images/simulator.jpeg\" alt=\"Simulator\"></p>\n<p>There are a few catches with working on wearOS apps when it comes to debugging, especially with a watch face. The first being the standard configuration. This will always finish building with the settings app open, which if you are working on watch face changes is a bit annoying. It’s better to have this as the configuration settings.</p>\n<p><img src=\"./images/wearconfig.jpeg\" alt=\"configSettings\"></p>\n<p>This way the app will build but nothing will change on the device or simulator. Next is setting up devices to debug the build on. There are two options here:</p>\n<h4>Simulator</h4>\n<p>Open up the Android Virtual Device Manager for this and select “create a new virtual device” at the bottom. Choose WearOS as your hardware, Select Pie as the system image but don’t select the Chinese version unless you specifically want that, everything else is fine on default so you can click finish.</p>\n<h4>Device</h4>\n<p>For this method, you should have an Android phone or tablet connected to your workstation already. Make sure it’s got developer settings enabled and has allowed your workstation access. You also need the Wear OS app installed on that device and Bluetooth connected to the wearable.</p>\n<p>Open the WearOS app on the Android device and scroll to the bottom where advanced settings are, at the bottom here is “Debugging over Bluetooth”. Turn that on and you should get “Host: Disconnected Target: Connected”. Once that’s done go into terminal and enter the following commands:</p>\n<div class=\"gatsby-highlight\" data-language=\"bash\"><pre class=\"language-bash\"><code class=\"language-bash\">adb forward tcp:4444 localabstract:/adb-hub\nadb connect 127.0.0.1:4444</code></pre></div>\n<p>Now your wearable should be fully connected and ready to debug</p>\n<h3>Manifest settings</h3>\n<p><img src=\"./images/manifest.jpeg\" alt=\"Manifest\"></p>\n<p>When making a wearable app and specifically a watch face, there are some permissions you need to have set in the manifest. They are:</p>\n<h5>Required for any of this to work on a wearable.</h5>\n<div class=\"gatsby-highlight\" data-language=\"xml\"><pre class=\"language-xml\"><code class=\"language-xml\"><span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;</span>uses-feature</span> <span class=\"token attr-name\"><span class=\"token namespace\">android:</span>name</span><span class=\"token attr-value\"><span class=\"token punctuation\">=</span><span class=\"token punctuation\">\"</span>android.hardware.type.watch<span class=\"token punctuation\">\"</span></span> <span class=\"token punctuation\">/></span></span></code></pre></div>\n<h5>Required to act as a custom watch face.</h5>\n<div class=\"gatsby-highlight\" data-language=\"xml\"><pre class=\"language-xml\"><code class=\"language-xml\"><span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;</span>uses-permission</span> <span class=\"token attr-name\"><span class=\"token namespace\">android:</span>name</span><span class=\"token attr-value\"><span class=\"token punctuation\">=</span><span class=\"token punctuation\">\"</span>android.permission.WAKE_LOCK<span class=\"token punctuation\">\"</span></span> <span class=\"token punctuation\">/></span></span></code></pre></div>\n<h5>Required for complications to receive complication data and open the provider chooser.</h5>\n<div class=\"gatsby-highlight\" data-language=\"xml\"><pre class=\"language-xml\"><code class=\"language-xml\"><span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;</span>uses-permission</span> \n<span class=\"token attr-name\"><span class=\"token namespace\">android:</span>name</span><span class=\"token attr-value\"><span class=\"token punctuation\">=</span><span class=\"token punctuation\">\"</span>com.google.android.wearable.permission.RECEIVE_COMPLICATION_DATA<span class=\"token punctuation\">\"</span></span>\n<span class=\"token punctuation\">/></span></span></code></pre></div>\n<p>Another set most apps will likely need is internet access, you will likely also need Bluetooth access as part of this if you want to communicate with the connected device.</p>\n<div class=\"gatsby-highlight\" data-language=\"xml\"><pre class=\"language-xml\"><code class=\"language-xml\"><span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;</span>uses-permission</span> <span class=\"token attr-name\"><span class=\"token namespace\">android:</span>name</span><span class=\"token attr-value\"><span class=\"token punctuation\">=</span><span class=\"token punctuation\">\"</span>android.permission.INTERNET<span class=\"token punctuation\">\"</span></span> <span class=\"token punctuation\">/></span></span>\n<span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;</span>uses-permission</span> <span class=\"token attr-name\"><span class=\"token namespace\">android:</span>name</span><span class=\"token attr-value\"><span class=\"token punctuation\">=</span><span class=\"token punctuation\">\"</span>android.permission.BLUETOOTH<span class=\"token punctuation\">\"</span></span> <span class=\"token punctuation\">/></span></span>\n<span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;</span>uses-permission</span> <span class=\"token attr-name\"><span class=\"token namespace\">android:</span>name</span><span class=\"token attr-value\"><span class=\"token punctuation\">=</span><span class=\"token punctuation\">\"</span>android.permission.ACCESS_NETWORK_STATE<span class=\"token punctuation\">\"</span></span> <span class=\"token punctuation\">/></span></span>\n<span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;</span>uses-permission</span> <span class=\"token attr-name\"><span class=\"token namespace\">android:</span>name</span><span class=\"token attr-value\"><span class=\"token punctuation\">=</span><span class=\"token punctuation\">\"</span>android.permission.FOREGROUND_SERVICE<span class=\"token punctuation\">\"</span></span> <span class=\"token punctuation\">/></span></span></code></pre></div>\n<p>Slightly less important is location services, Turtle wear needs this information to get weather data for your location.</p>\n<div class=\"gatsby-highlight\" data-language=\"xml\"><pre class=\"language-xml\"><code class=\"language-xml\"><span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;</span>uses-permission</span> <span class=\"token attr-name\"><span class=\"token namespace\">android:</span>name</span><span class=\"token attr-value\"><span class=\"token punctuation\">=</span><span class=\"token punctuation\">\"</span>android.permission.ACCESS_COARSE_LOCATION<span class=\"token punctuation\">\"</span></span> <span class=\"token punctuation\">/></span></span>\n<span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;</span>uses-permission</span> <span class=\"token attr-name\"><span class=\"token namespace\">android:</span>name</span><span class=\"token attr-value\"><span class=\"token punctuation\">=</span><span class=\"token punctuation\">\"</span>android.permission.ACCESS_FINE_LOCATION<span class=\"token punctuation\">\"</span></span> <span class=\"token punctuation\">/></span></span></code></pre></div>\n<p>For the CanvasWatchFaceService, it need to be declared specifically as a watch face. So we start by flagging it as a service and giving it the Bind Wallpaper permission.</p>\n<div class=\"gatsby-highlight\" data-language=\"xml\"><pre class=\"language-xml\"><code class=\"language-xml\"><span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;</span>service</span>\n<span class=\"token attr-name\"><span class=\"token namespace\">android:</span>name</span><span class=\"token attr-value\"><span class=\"token punctuation\">=</span><span class=\"token punctuation\">\"</span>.watchface<span class=\"token punctuation\">\"</span></span>\n<span class=\"token attr-name\"><span class=\"token namespace\">android:</span>label</span><span class=\"token attr-value\"><span class=\"token punctuation\">=</span><span class=\"token punctuation\">\"</span>@string/my_name<span class=\"token punctuation\">\"</span></span>\n<span class=\"token attr-name\"><span class=\"token namespace\">android:</span>permission</span><span class=\"token attr-value\"><span class=\"token punctuation\">=</span><span class=\"token punctuation\">\"</span>android.permission.BIND_WALLPAPER<span class=\"token punctuation\">\"</span></span><span class=\"token punctuation\">></span></span></code></pre></div>\n<p>Next, we set up the metadata for the watch face and what the watch face example screen looks like on a square and circular screen type. The examples are used when the user selects the watch face from the selection screen.</p>\n<div class=\"gatsby-highlight\" data-language=\"xml\"><pre class=\"language-xml\"><code class=\"language-xml\"><span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;</span>meta-data</span>\n<span class=\"token attr-name\"><span class=\"token namespace\">android:</span>name</span><span class=\"token attr-value\"><span class=\"token punctuation\">=</span><span class=\"token punctuation\">\"</span>android.service.wallpaper<span class=\"token punctuation\">\"</span></span>\n<span class=\"token attr-name\"><span class=\"token namespace\">android:</span>resource</span><span class=\"token attr-value\"><span class=\"token punctuation\">=</span><span class=\"token punctuation\">\"</span>@xml/watch_face<span class=\"token punctuation\">\"</span></span> <span class=\"token punctuation\">/></span></span>\n<span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;</span>meta-data</span>\n<span class=\"token attr-name\"><span class=\"token namespace\">android:</span>name</span><span class=\"token attr-value\"><span class=\"token punctuation\">=</span><span class=\"token punctuation\">\"</span>com.google.android.wearable.watchface.preview<span class=\"token punctuation\">\"</span></span>\n<span class=\"token attr-name\"><span class=\"token namespace\">android:</span>resource</span><span class=\"token attr-value\"><span class=\"token punctuation\">=</span><span class=\"token punctuation\">\"</span>@drawable/preview_digital<span class=\"token punctuation\">\"</span></span> <span class=\"token punctuation\">/></span></span>\n<span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;</span>meta-data</span>\n<span class=\"token attr-name\"><span class=\"token namespace\">android:</span>name</span><span class=\"token attr-value\"><span class=\"token punctuation\">=</span><span class=\"token punctuation\">\"</span>com.google.android.wearable.watchface.preview_circular<span class=\"token punctuation\">\"</span></span>\n<span class=\"token attr-name\"><span class=\"token namespace\">android:</span>resource</span><span class=\"token attr-value\"><span class=\"token punctuation\">=</span><span class=\"token punctuation\">\"</span>@drawable/preview_digital_circular<span class=\"token punctuation\">\"</span></span> <span class=\"token punctuation\">/></span></span></code></pre></div>\n<p>The last part is identifying it as a watch face.</p>\n<div class=\"gatsby-highlight\" data-language=\"xml\"><pre class=\"language-xml\"><code class=\"language-xml\"><span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;</span>intent-filter</span><span class=\"token punctuation\">></span></span>\n<span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;</span>action</span> <span class=\"token attr-name\"><span class=\"token namespace\">android:</span>name</span><span class=\"token attr-value\"><span class=\"token punctuation\">=</span><span class=\"token punctuation\">\"</span>android.service.wallpaper.WallpaperService<span class=\"token punctuation\">\"</span></span> <span class=\"token punctuation\">/></span></span>\n<span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;</span>category</span> \n<span class=\"token attr-name\"><span class=\"token namespace\">android:</span>name</span><span class=\"token attr-value\"><span class=\"token punctuation\">=</span><span class=\"token punctuation\">\"</span>com.google.android.wearable.watchface.category.WATCH_FACE<span class=\"token punctuation\">\"</span></span> \n<span class=\"token punctuation\">/></span></span>\n<span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;/</span>intent-filter</span><span class=\"token punctuation\">></span></span>\n<span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;/</span>service</span><span class=\"token punctuation\">></span></span></code></pre></div>\n<p>The main activity manifest setup is thankfully very default android.</p>\n<div class=\"gatsby-highlight\" data-language=\"xml\"><pre class=\"language-xml\"><code class=\"language-xml\"><span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;</span>activity</span>\n<span class=\"token attr-name\"><span class=\"token namespace\">android:</span>label</span><span class=\"token attr-value\"><span class=\"token punctuation\">=</span><span class=\"token punctuation\">\"</span>@string/app_name<span class=\"token punctuation\">\"</span></span>\n<span class=\"token attr-name\"><span class=\"token namespace\">android:</span>name</span><span class=\"token attr-value\"><span class=\"token punctuation\">=</span><span class=\"token punctuation\">\"</span>.MainActivity<span class=\"token punctuation\">\"</span></span><span class=\"token punctuation\">></span></span>\n<span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;</span>intent-filter</span><span class=\"token punctuation\">></span></span>\n<span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;</span>action</span> <span class=\"token attr-name\"><span class=\"token namespace\">android:</span>name</span><span class=\"token attr-value\"><span class=\"token punctuation\">=</span><span class=\"token punctuation\">\"</span>android.intent.action.MAIN<span class=\"token punctuation\">\"</span></span><span class=\"token punctuation\">/></span></span>\n<span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;</span>action</span> <span class=\"token attr-name\"><span class=\"token namespace\">android:</span>name</span><span class=\"token attr-value\"><span class=\"token punctuation\">=</span><span class=\"token punctuation\">\"</span>android.intent.action.VIEW<span class=\"token punctuation\">\"</span></span><span class=\"token punctuation\">/></span></span>\n<span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;</span>category</span> <span class=\"token attr-name\"><span class=\"token namespace\">android:</span>name</span><span class=\"token attr-value\"><span class=\"token punctuation\">=</span><span class=\"token punctuation\">\"</span>android.intent.category.LAUNCHER<span class=\"token punctuation\">\"</span></span><span class=\"token punctuation\">/></span></span>\n<span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;/</span>intent-filter</span><span class=\"token punctuation\">></span></span>\n<span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;/</span>activity</span><span class=\"token punctuation\">></span></span></code></pre></div>\n<h2>Important</h2>\n<p>Without this inside the application area of the manifest, you will not be able to make any API calls out from the phone on newer devices. The error messaging on this is vague so it took ages for me to find this.</p>\n<div class=\"gatsby-highlight\" data-language=\"xml\"><pre class=\"language-xml\"><code class=\"language-xml\">android:usesCleartextTraffic=\"true”</code></pre></div>\n<h3>Drawing the watch face</h3>\n<p><img src=\"./images/watchface.jpeg\" alt=\"Watch\"></p>\n<p>If you check most places for how to draw the watch face, you will generally see very large OnDraw functions that require canvas drawing. I instead prefer to use xml layouts in the same way you would with an android application. This is a little less efficient but a lot more readable code in my opinion. To set this up first have a lateinit View outside the engine. Then on the OnCreate you inflate it like this:</p>\n<div class=\"gatsby-highlight\" data-language=\"java\"><pre class=\"language-java\"><code class=\"language-java\">val inflater<span class=\"token operator\">:</span> LayoutInflater <span class=\"token operator\">=</span> \n<span class=\"token function\">getSystemService</span><span class=\"token punctuation\">(</span>Context<span class=\"token punctuation\">.</span>LAYOUT_INFLATER_SERVICE<span class=\"token punctuation\">)</span> as LayoutInflater\nwatchLayout <span class=\"token operator\">=</span> inflater<span class=\"token punctuation\">.</span><span class=\"token function\">inflate</span><span class=\"token punctuation\">(</span>R<span class=\"token punctuation\">.</span>layout<span class=\"token punctuation\">.</span>watchface<span class=\"token punctuation\">,</span> null<span class=\"token punctuation\">)</span></code></pre></div>\n<p>With the view now inflated, you can set it up with the screen dimensions on the OnDraw like below.</p>\n<div class=\"gatsby-highlight\" data-language=\"java\"><pre class=\"language-java\"><code class=\"language-java\">watchLayout<span class=\"token punctuation\">.</span><span class=\"token function\">measure</span><span class=\"token punctuation\">(</span>specW<span class=\"token punctuation\">,</span> specH<span class=\"token punctuation\">)</span>\nwatchLayout<span class=\"token punctuation\">.</span><span class=\"token function\">layout</span><span class=\"token punctuation\">(</span><span class=\"token number\">0</span><span class=\"token punctuation\">,</span> <span class=\"token number\">0</span><span class=\"token punctuation\">,</span> watchLayout<span class=\"token punctuation\">.</span>measuredWidth<span class=\"token punctuation\">,</span> watchLayout<span class=\"token punctuation\">.</span>measuredHeight<span class=\"token punctuation\">)</span>\ncanvas<span class=\"token punctuation\">.</span><span class=\"token function\">save</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span>\ncanvas<span class=\"token punctuation\">.</span><span class=\"token function\">translate</span><span class=\"token punctuation\">(</span>mXOffset<span class=\"token punctuation\">,</span> mYOffset <span class=\"token operator\">-</span> <span class=\"token number\">40</span><span class=\"token punctuation\">)</span>\nwatchLayout<span class=\"token punctuation\">.</span><span class=\"token function\">draw</span><span class=\"token punctuation\">(</span>canvas<span class=\"token punctuation\">)</span>\ncanvas<span class=\"token punctuation\">.</span><span class=\"token function\">restore</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span></code></pre></div>\n<p>With that done, you now call any element you need to update wherever you need. For example, this is called on the OnDraw elsewhere for showing the current time.</p>\n<div class=\"gatsby-highlight\" data-language=\"java\"><pre class=\"language-java\"><code class=\"language-java\"><span class=\"token keyword\">private</span> fun <span class=\"token function\">setTimeandDate</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">{</span>\n      val now <span class=\"token operator\">=</span> System<span class=\"token punctuation\">.</span><span class=\"token function\">currentTimeMillis</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span>\n      mCalendar<span class=\"token punctuation\">.</span>timeInMillis <span class=\"token operator\">=</span> now\n      val date<span class=\"token operator\">:</span> TextView <span class=\"token operator\">=</span> watchLayout<span class=\"token punctuation\">.</span><span class=\"token function\">findViewById</span><span class=\"token punctuation\">(</span>R<span class=\"token punctuation\">.</span>id<span class=\"token punctuation\">.</span>date_number<span class=\"token punctuation\">)</span>\n      date<span class=\"token punctuation\">.</span>text <span class=\"token operator\">=</span> String<span class=\"token punctuation\">.</span><span class=\"token function\">format</span><span class=\"token punctuation\">(</span><span class=\"token string\">\"%02d/%02d\"</span><span class=\"token punctuation\">,</span> \n      mCalendar<span class=\"token punctuation\">.</span><span class=\"token function\">get</span><span class=\"token punctuation\">(</span>Calendar<span class=\"token punctuation\">.</span>DAY_OF_MONTH<span class=\"token punctuation\">)</span><span class=\"token punctuation\">,</span> \n      mCalendar<span class=\"token punctuation\">.</span><span class=\"token function\">get</span><span class=\"token punctuation\">(</span>Calendar<span class=\"token punctuation\">.</span>MONTH<span class=\"token punctuation\">)</span> <span class=\"token operator\">+</span> <span class=\"token number\">1</span><span class=\"token punctuation\">)</span>\n      val hour<span class=\"token operator\">:</span> TextView <span class=\"token operator\">=</span> watchLayout<span class=\"token punctuation\">.</span><span class=\"token function\">findViewById</span><span class=\"token punctuation\">(</span>R<span class=\"token punctuation\">.</span>id<span class=\"token punctuation\">.</span>hourtime<span class=\"token punctuation\">)</span>\n      hour<span class=\"token punctuation\">.</span>text <span class=\"token operator\">=</span> String<span class=\"token punctuation\">.</span><span class=\"token function\">format</span><span class=\"token punctuation\">(</span><span class=\"token string\">\"%02d\"</span><span class=\"token punctuation\">,</span> mCalendar<span class=\"token punctuation\">.</span><span class=\"token function\">get</span><span class=\"token punctuation\">(</span>Calendar<span class=\"token punctuation\">.</span>HOUR_OF_DAY<span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span>\n      val min<span class=\"token operator\">:</span> TextView <span class=\"token operator\">=</span> watchLayout<span class=\"token punctuation\">.</span><span class=\"token function\">findViewById</span><span class=\"token punctuation\">(</span>R<span class=\"token punctuation\">.</span>id<span class=\"token punctuation\">.</span>mintime<span class=\"token punctuation\">)</span>\n      min<span class=\"token punctuation\">.</span>text <span class=\"token operator\">=</span> String<span class=\"token punctuation\">.</span><span class=\"token function\">format</span><span class=\"token punctuation\">(</span><span class=\"token string\">\"%02d\"</span><span class=\"token punctuation\">,</span> mCalendar<span class=\"token punctuation\">.</span><span class=\"token function\">get</span><span class=\"token punctuation\">(</span>Calendar<span class=\"token punctuation\">.</span>MINUTE<span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span>\n    <span class=\"token punctuation\">}</span></code></pre></div>\n<h3>Finishing it up and launching</h3>\n<p><img src=\"./images/launch.jpeg\" alt=\"Launch\"></p>\n<p>That’s mostly in terms of the tricky bits of getting the Turtle wear v2 up and running. The Google play store takes submissions to it just the same as it would an Android app.</p>\n<ul>\n<li><a href=\"https://github.com/seperot/turtle-wear\">You can check the github repo here</a></li>\n<li><a href=\"https://play.google.com/store/apps/details?id=uk.co.ijhdev.trtlware&#x26;hl=en\">You can download the watch face here</a></li>\n<li>If your interested in taking your build further with a CI/CD pipeline, <a href=\"https://ijh.dev/mobile-ci-cd\">I’ve got a blog post all about how to set one up here</a></li>\n</ul>","frontmatter":{"title":"Building a WearOS Watch face","date":"November 18, 2019","featuredImage":{"childImageSharp":{"sizes":{"base64":"data:image/jpeg;base64,/9j/2wBDABALDA4MChAODQ4SERATGCgaGBYWGDEjJR0oOjM9PDkzODdASFxOQERXRTc4UG1RV19iZ2hnPk1xeXBkeFxlZ2P/2wBDARESEhgVGC8aGi9jQjhCY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2P/wgARCAAIABQDASIAAhEBAxEB/8QAFgABAQEAAAAAAAAAAAAAAAAAAAEE/8QAFQEBAQAAAAAAAAAAAAAAAAAAAAL/2gAMAwEAAhADEAAAAcUKig//xAAYEAADAQEAAAAAAAAAAAAAAAAAARMREv/aAAgBAQABBQKaONJo/8QAFBEBAAAAAAAAAAAAAAAAAAAAEP/aAAgBAwEBPwE//8QAFBEBAAAAAAAAAAAAAAAAAAAAEP/aAAgBAgEBPwE//8QAFBABAAAAAAAAAAAAAAAAAAAAEP/aAAgBAQAGPwJ//8QAGRAAAgMBAAAAAAAAAAAAAAAAAREAECFB/9oACAEBAAE/IZAOEsq//9oADAMBAAIAAwAAABAAD//EABYRAAMAAAAAAAAAAAAAAAAAAAABEf/aAAgBAwEBPxCIiP/EABURAQEAAAAAAAAAAAAAAAAAAAAR/9oACAECAQE/EFf/xAAZEAACAwEAAAAAAAAAAAAAAAAAEQEhYVH/2gAIAQEAAT8Q0H8I23TQ/9k=","aspectRatio":2.4518388791593697,"src":"/static/trtlwearbig-040e897d594d2e7aa6b51466324174e4-6b3a1.jpg","srcSet":"/static/trtlwearbig-040e897d594d2e7aa6b51466324174e4-182ff.jpg 213w,\n/static/trtlwearbig-040e897d594d2e7aa6b51466324174e4-7f5c7.jpg 425w,\n/static/trtlwearbig-040e897d594d2e7aa6b51466324174e4-6b3a1.jpg 850w,\n/static/trtlwearbig-040e897d594d2e7aa6b51466324174e4-45cc1.jpg 1275w,\n/static/trtlwearbig-040e897d594d2e7aa6b51466324174e4-055dc.jpg 1400w","sizes":"(max-width: 850px) 100vw, 850px"}}}}}},"pageContext":{"slug":"/making-wear-os/","previous":{"fields":{"slug":"/making-magic-mirror/"},"excerpt":"A smart mirror build with spotify added in\n","frontmatter":{"title":"Making a Smart Mirror","date":"October 10, 2019","featuredImage":{"childImageSharp":{"sizes":{"base64":"data:image/jpeg;base64,/9j/2wBDABALDA4MChAODQ4SERATGCgaGBYWGDEjJR0oOjM9PDkzODdASFxOQERXRTc4UG1RV19iZ2hnPk1xeXBkeFxlZ2P/2wBDARESEhgVGC8aGi9jQjhCY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2P/wgARCAAIABQDASIAAhEBAxEB/8QAFgABAQEAAAAAAAAAAAAAAAAAAAIF/8QAFQEBAQAAAAAAAAAAAAAAAAAAAAH/2gAMAwEAAhADEAAAAcGyIB//xAAWEAADAAAAAAAAAAAAAAAAAAAAECH/2gAIAQEAAQUCIv/EABQRAQAAAAAAAAAAAAAAAAAAABD/2gAIAQMBAT8BP//EABQRAQAAAAAAAAAAAAAAAAAAABD/2gAIAQIBAT8BP//EABQQAQAAAAAAAAAAAAAAAAAAABD/2gAIAQEABj8Cf//EABgQAAMBAQAAAAAAAAAAAAAAAAABIREx/9oACAEBAAE/IVhSXDLD/9oADAMBAAIAAwAAABADz//EABQRAQAAAAAAAAAAAAAAAAAAABD/2gAIAQMBAT8QP//EABYRAQEBAAAAAAAAAAAAAAAAAAABEf/aAAgBAgEBPxCtf//EABkQAQEBAQEBAAAAAAAAAAAAAAERACExYf/aAAgBAQABPxD0WfMEiEe3KqBLyJv/2Q==","aspectRatio":2.4518388791593697,"src":"/static/mirrormain-eb95d453870867599e5ae2f96e0ab091-6b3a1.jpg","srcSet":"/static/mirrormain-eb95d453870867599e5ae2f96e0ab091-182ff.jpg 213w,\n/static/mirrormain-eb95d453870867599e5ae2f96e0ab091-7f5c7.jpg 425w,\n/static/mirrormain-eb95d453870867599e5ae2f96e0ab091-6b3a1.jpg 850w,\n/static/mirrormain-eb95d453870867599e5ae2f96e0ab091-45cc1.jpg 1275w,\n/static/mirrormain-eb95d453870867599e5ae2f96e0ab091-055dc.jpg 1400w","sizes":"(max-width: 850px) 100vw, 850px"}}}}},"next":{"fields":{"slug":"/open-source-pipeline/"},"excerpt":"A guide to building a simple pipeline from PR to deploy with a scalable solution. (TurtleWare 2.0 pt3)\n","frontmatter":{"title":"Golang automated pipeline","date":"December 9, 2019","featuredImage":{"childImageSharp":{"sizes":{"base64":"data:image/jpeg;base64,/9j/2wBDABALDA4MChAODQ4SERATGCgaGBYWGDEjJR0oOjM9PDkzODdASFxOQERXRTc4UG1RV19iZ2hnPk1xeXBkeFxlZ2P/2wBDARESEhgVGC8aGi9jQjhCY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2P/wgARCAAIABQDASIAAhEBAxEB/8QAFgABAQEAAAAAAAAAAAAAAAAAAAMF/8QAFQEBAQAAAAAAAAAAAAAAAAAAAAH/2gAMAwEAAhADEAAAAduZZQH/xAAWEAEBAQAAAAAAAAAAAAAAAAABABD/2gAIAQEAAQUChc//xAAUEQEAAAAAAAAAAAAAAAAAAAAQ/9oACAEDAQE/AT//xAAUEQEAAAAAAAAAAAAAAAAAAAAQ/9oACAECAQE/AT//xAAWEAADAAAAAAAAAAAAAAAAAAAAECL/2gAIAQEABj8CKX//xAAZEAACAwEAAAAAAAAAAAAAAAABEQAQIVH/2gAIAQEAAT8hmlAOIuv/2gAMAwEAAgADAAAAEHAf/8QAFREBAQAAAAAAAAAAAAAAAAAAARD/2gAIAQMBAT8QZ//EABQRAQAAAAAAAAAAAAAAAAAAABD/2gAIAQIBAT8QP//EABoQAAMAAwEAAAAAAAAAAAAAAAABETFBgaH/2gAIAQEAAT8QdjkuqKelDmROqo//2Q==","aspectRatio":2.4518388791593697,"src":"/static/goline-62aadd8af557846018fcb4e9333040a7-6b3a1.jpg","srcSet":"/static/goline-62aadd8af557846018fcb4e9333040a7-182ff.jpg 213w,\n/static/goline-62aadd8af557846018fcb4e9333040a7-7f5c7.jpg 425w,\n/static/goline-62aadd8af557846018fcb4e9333040a7-6b3a1.jpg 850w,\n/static/goline-62aadd8af557846018fcb4e9333040a7-45cc1.jpg 1275w,\n/static/goline-62aadd8af557846018fcb4e9333040a7-055dc.jpg 1400w","sizes":"(max-width: 850px) 100vw, 850px"}}}}}}}