{"id":348482,"date":"2025-09-25T16:32:46","date_gmt":"2025-09-25T21:32:46","guid":{"rendered":"https:\/\/michigandigitalnews.com\/index.php\/2025\/09\/25\/further-explorations-with-watch-face-push\/"},"modified":"2025-09-25T16:32:46","modified_gmt":"2025-09-25T21:32:46","slug":"further-explorations-with-watch-face-push","status":"publish","type":"post","link":"https:\/\/michigandigitalnews.com\/index.php\/2025\/09\/25\/further-explorations-with-watch-face-push\/","title":{"rendered":"Further explorations with Watch Face Push"},"content":{"rendered":"<p> [ad_1]<br \/>\n<\/p>\n<div>\n<meta name=\"twitter:image\" content=\"https:\/\/blogger.googleusercontent.com\/img\/b\/R29vZ2xl\/AVvXsEg9hPoEMQhoOUSubWVgO-U3FPA17XPYAfWC0TTYoNJu74a2hXCiWBrRM-jacwcSbAMh8smzUt_oh2lk1MpicWicpLKpB4nhPNVfOAv5-m9r1eIe_5ScQbRRuUDbNYnup4pa5z382RJpf_-VRWD1zd58Gi9AOm6ou5HAw7HBRBBFtqEGQ5zIuPJW76vUBSQ\/s1600\/watch-face-push.png\"\/><br \/>\n<img decoding=\"async\" src=\"https:\/\/blogger.googleusercontent.com\/img\/b\/R29vZ2xl\/AVvXsEg9hPoEMQhoOUSubWVgO-U3FPA17XPYAfWC0TTYoNJu74a2hXCiWBrRM-jacwcSbAMh8smzUt_oh2lk1MpicWicpLKpB4nhPNVfOAv5-m9r1eIe_5ScQbRRuUDbNYnup4pa5z382RJpf_-VRWD1zd58Gi9AOm6ou5HAw7HBRBBFtqEGQ5zIuPJW76vUBSQ\/s1600\/watch-face-push.png\" style=\"display:none\"\/><\/p>\n<p><em>Posted by Garan Jenkin \u2013 Developer Relations Engineer<\/em><\/p>\n<blockquote><p><i>This post is part of <a href=\"https:\/\/android-developers.googleblog.com\/2025\/08\/spotlight-week-wear-os.html\" target=\"_blank\" rel=\"noopener\">Wear OS Spotlight Week<\/a>. Today, we&#8217;re <b>exploring the wonderful world of watch faces<\/b>.<\/i><\/p><\/blockquote>\n<p>At Google I\/O \u201825 we launched <a href=\"https:\/\/developer.android.com\/training\/wearables\/watch-face-push\" target=\"_blank\" rel=\"noopener\">Watch Face Push<\/a>, a new API aimed at enabling watch face marketplaces for watch and phone. Watch Face Push is now available to develop with and use on Wear OS 6 on devices such as the recently-launched <a href=\"https:\/\/android-developers.googleblog.com\/2025\/08\/build-your-app-to-meet-users-on-newest-pixel-devices.html\" target=\"_blank\" rel=\"noopener\">Pixel Watch 4<\/a>.<\/p>\n<p>In this blog post, we\u2019ll show how Watch Face Push (WFP) can be used in a whole host of other ways, including:<\/p>\n<ul>\n<ul>\n<li>Dynamically theming a watch face from a photo<\/li>\n<li>Presenting rich data or photos from online or connected data sources<\/li>\n<li>Complementing a phone app to drive engagement<\/li>\n<\/ul>\n<\/ul>\n<p><\/p>\n<p><image><\/p>\n<div style=\"text-align: center;\"><img decoding=\"async\" alt=\"illustration of using Watch Face Push to build a watch face with dynamic colors, updated from the phone\" border=\"0\" id=\"imgCaption\" src=\"https:\/\/blogger.googleusercontent.com\/img\/b\/R29vZ2xl\/AVvXsEj5BNn-eFschBMOkZae4r0sNEjAQx9NREnLJWHC91SxzgcNN-x7ndLg6A3vBXizg62vzkCXN0Cy6pxX2-LDIPJhnpVgg881N7w8wwU5l5NoLPP3X8RL40d5713sep3mkgfhDZ0oLkIrVoLtS0LnEcHARgkHneRpvXOLx89rQlUwtwcLKA8qzfoCA0hexEM\/s1600\/updating-watch-face-push-dynamic-colors-from-phone.png\" width=\"50%\"\/><\/div>\n<p><imgcaption><center><em>Illustration of using Watch Face Push to build a watch face with dynamic colors, updated from the phone<\/em><\/center><\/imgcaption><\/image><\/p>\n<p>The first example we\u2019ll focus on is building a watch face with an accompanying phone app. It can apply a color theme based on a photo taken on the phone &#8211; perfect for matching your watch face to your outfit! And it\u2019s perfect for demonstrating how Watch Face Push allows developers to bring dynamic data to the watch face.<\/p>\n<p>Let\u2019s go through some of the main techniques which combine together to make this possible:<\/p>\n<h2><span style=\"font-size: x-large;\">The default watch face &#8211; bringing components together<\/span><\/h2>\n<p>A powerful feature of Watch Face Push is the <a href=\"https:\/\/developer.android.com\/training\/wearables\/watch-face-push\/wear-os-app#supply-default-watch-face\" target=\"_blank\" rel=\"noopener\">default watch face<\/a> feature. This allows the developer to provide a watch face that\u2019s installed onto the Wear OS device at the same time as the overall app. This watch face is bundled as an APK and placed in the <span style=\"color: #0d904f ;font-family: courier;\">assets<\/span> directory in the app.<\/p>\n<p>The system checks for the presence of this APK as the app is being installed, and it checks for the <a href=\"https:\/\/developer.android.com\/training\/wearables\/watch-face-push#validation\" target=\"_blank\" rel=\"noopener\">validation<\/a> key in the app\u2019s manifest.<\/p>\n<p>This enables you to deliver a single package that contains both the watch face and app components, whether that\u2019s a full Wear OS app, where the app is the primary focus, or app components such as complication providers, where the watch face is the primary focus.<\/p>\n<p>In our project structure, we define two modules, <span style=\"color: #0d904f ;font-family: courier;\">wear<\/span> and <span style=\"color: #0d904f ;font-family: courier;\">watchface<\/span>. By using a unified <span style=\"color: #0d904f ;font-family: courier;\">versionCode<\/span> across both, we can keep the app and watch face versions in sync. We use <a href=\"https:\/\/developer.android.com\/build\/gradle-build-overview\" target=\"_blank\" rel=\"noopener\">Gradle<\/a> to build the watch face and generate the validation token. This makes it easy to treat the watch face and the app as part of the same project.<\/p>\n<h2><span style=\"font-size: x-large;\">Complication data sources &#8211; pipelines for data<\/span><\/h2>\n<p>Now that we\u2019ve successfully supplied both watch face and app components together, we need a way to provide data.<\/p>\n<p>The watch face is now able to rely on the presence of <a href=\"https:\/\/developer.android.com\/training\/wearables\/complications\/exposing-data\" target=\"_blank\" rel=\"noopener\">complication data sources<\/a> provided by the app. For example, a surfing watch face could bundle with a water temperature complication. This can be set as the default on the watch face using <span style=\"font-family: courier;\"><a href=\"https:\/\/developer.android.com\/reference\/wear-os\/wff\/complication\/default-provider-policy\" target=\"_blank\" rel=\"noopener\">DefaultProviderPolicy<\/a><\/span> and is guaranteed to be present.<\/p>\n<p>Taking it a step further, we can configure the <a href=\"https:\/\/developer.android.com\/training\/wearables\/wff\/complications\" target=\"_blank\" rel=\"noopener\">complication<\/a> to be non-customizable, so that the complication becomes more of a custom data source. We can then use the complication however the watch face may need:<\/p>\n<p><!-- Kotlin --><\/p>\n<div style=\"background: #f8f8f8; overflow:auto;width:auto;border:0;\">\n<pre style=\"margin: 0; line-height: 125%;\"><span\/><span style=\"color: #666\">&lt;<\/span>ComplicationSlot<span style=\"color: #BBB\"> <\/span>isCustomizable<span style=\"color: #666\">=<\/span><span style=\"color: #BA2121\">\"FALSE\"<\/span><span style=\"color: #BBB\"> <\/span>...<span style=\"color: #BBB\"> <\/span><span style=\"color: #666\">&gt;<\/span>\n<span style=\"color: #BBB\">    <\/span><span style=\"color: #666\">&lt;<\/span>DefaultProviderPolicy\n<span style=\"color: #BBB\">        <\/span>defaultSystemProvider<span style=\"color: #666\">=<\/span><span style=\"color: #BA2121\">\"NEXT_EVENT\"<\/span>\n<span style=\"color: #BBB\">        <\/span>defaultSystemProviderType<span style=\"color: #666\">=<\/span><span style=\"color: #BA2121\">\"SHORT_TEXT\"<\/span>\n<span style=\"color: #BBB\">        <\/span>primaryProvider<span style=\"color: #666\">=<\/span><span style=\"color: #BA2121\">\"<my_component_path>\"<\/my_component_path><\/span>\n<span style=\"color: #BBB\">        <\/span>primaryProviderType<span style=\"color: #666\">=<\/span><span style=\"color: #BA2121\">\"SHORT_TEXT\"<\/span><span style=\"color: #BBB\"> <\/span><span style=\"color: #666\">\/&gt;<\/span>\n\n<span style=\"color: #BBB\">   <\/span><span style=\"color: #666\"><!--<\/span><span style=\"color: #BBB\"> <\/span>Rest<span style=\"color: #BBB\"> <\/span>of<span style=\"color: #BBB\"> <\/span>complication<span style=\"color: #BBB\"> <\/span>goes<span style=\"color: #BBB\"> <\/span>here<span style=\"color: #BBB\"> <\/span><span style=\"color: #666\">--><\/span>\n\n<span style=\"color: #666\"\/>ComplicationSlot<span style=\"color: #666\">&gt;<\/span>\n<\/pre>\n<\/div>\n<p>In the case of our watch face, we define a <span style=\"color: #0d904f ;font-family: courier;\">SHORT_TEXT<\/span> complication service <span style=\"color: #0d904f ;font-family: courier;\">PaletteComplicationService<\/span>, which sends the following data:<\/p>\n<p><!-- Kotlin --><\/p>\n<div style=\"background: #f8f8f8; overflow:auto;width:auto;border:0;\">\n<pre style=\"margin: 0; line-height: 125%;\"><span\/>TEXT:<span style=\"color: #BBB\"> <\/span><span style=\"color: #666\">&lt;<\/span>space<span style=\"color: #666\">-<\/span>delimited<span style=\"color: #BBB\"> <\/span>list<span style=\"color: #BBB\"> <\/span>of<span style=\"color: #BBB\"> <\/span>RGB<span style=\"color: #BBB\"> <\/span>hex<span style=\"color: #BBB\"> <\/span>values<span style=\"color: #666\">&gt;<\/span>\nTITLE:<span style=\"color: #BBB\"> <\/span>CONFIGURED<span style=\"color: #BBB\"> <\/span><span style=\"color: #666\">|<\/span><span style=\"color: #BBB\"> <\/span>NOT_CONFIGURED\n<\/pre>\n<\/div>\n<p>By using two of the fields on <span style=\"color: #0d904f ;font-family: courier;\">SHORT_TEXT<\/span>, we\u2019re able to send our color palette to the watch face, along with an indicator of whether the app has been configured (more on why that is important later).<\/p>\n<h2><span style=\"font-size: x-large;\">Extracting and manipulating complication data<\/span><\/h2>\n<p>We\u2019ve demonstrated how using the guaranteed presence of the <span style=\"color: #0d904f ;font-family: courier;\">PaletteComplicationService<\/span> allows us to ensure the watch face can receive our data, but we still need to define how to use and show the data within watch face elements.<\/p>\n<p>Within the <span style=\"font-family: courier;\"><a href=\"https:\/\/developer.android.com\/reference\/wear-os\/wff\/complication\/complication-slot?version=4\" target=\"_blank\" rel=\"noopener\">ComplicationSlot<\/a><\/span> element on the watch face, these data items can be accessed as <span style=\"color: #0d904f ;font-family: courier;\">COMPLICATION.TEXT<\/span> and <span style=\"color: #0d904f ;font-family: courier;\">COMPLICATION.TITLE<\/span> respectively. The various <a href=\"https:\/\/developer.android.com\/reference\/wear-os\/wff\/common\/attributes\/arithmetic-expression#functions\" target=\"_blank\" rel=\"noopener\">functions<\/a> such as <span style=\"color: #0d904f ;font-family: courier;\">abs()<\/span> and <span style=\"color: #0d904f ;font-family: courier;\">subText()<\/span> can be used to extract parts of these strings, or convert them into numeric types.<\/p>\n<p>We combine this with the use of <span style=\"font-family: courier;\"><a href=\"https:\/\/developer.android.com\/reference\/wear-os\/wff\/common\/reference\/reference\" target=\"_blank\" rel=\"noopener\">REFERENCE<\/a><\/span> to define colors. We can retrieve these colors everywhere on the watch, including outside of the <span style=\"color: #0d904f ;font-family: courier;\">ComplicationSlot<\/span>:<\/p>\n<p><!-- Kotlin --><\/p>\n<div style=\"background: #f8f8f8; overflow:auto;width:auto;border:0;\">\n<pre style=\"margin: 0; line-height: 125%;\"><span\/><span style=\"color: #666\">&lt;<\/span>ComplicationSlot<span style=\"color: #BBB\"> <\/span>...\n<span style=\"color: #BBB\">    <\/span>isCustomizable<span style=\"color: #666\">=<\/span><span style=\"color: #BA2121\">\"FALSE\"<\/span>\n<span style=\"color: #BBB\">    <\/span>x<span style=\"color: #666\">=<\/span><span style=\"color: #BA2121\">\"0\"<\/span><span style=\"color: #BBB\"> <\/span>y<span style=\"color: #666\">=<\/span><span style=\"color: #BA2121\">\"0\"<\/span><span style=\"color: #BBB\"> <\/span>width<span style=\"color: #666\">=<\/span><span style=\"color: #BA2121\">\"1\"<\/span><span style=\"color: #BBB\"> <\/span>height<span style=\"color: #666\">=<\/span><span style=\"color: #BA2121\">\"1\"<\/span><span style=\"color: #666\">&gt;<\/span>\n<span style=\"color: #BBB\">  <\/span><span style=\"color: #666\">&lt;<\/span>DefaultProviderPolicy\n<span style=\"color: #BBB\">      <\/span>defaultSystemProvider<span style=\"color: #666\">=<\/span><span style=\"color: #BA2121\">\"NEXT_EVENT\"<\/span>\n<span style=\"color: #BBB\">      <\/span>defaultSystemProviderType<span style=\"color: #666\">=<\/span><span style=\"color: #BA2121\">\"SHORT_TEXT\"<\/span>\n<span style=\"color: #BBB\">    <\/span>primaryProvider<span style=\"color: #666\">=<\/span><span style=\"color: #BA2121\">\"com.example.palette\/com.example.palette.complication.PaletteComplicationService\"<\/span>\n<span style=\"color: #BBB\">      <\/span>primaryProviderType<span style=\"color: #666\">=<\/span><span style=\"color: #BA2121\">\"SHORT_TEXT\"<\/span><span style=\"color: #BBB\"> <\/span><span style=\"color: #666\">\/&gt;<\/span>\n<span style=\"color: #BBB\">  <\/span><span style=\"color: #666\">&lt;<\/span>BoundingBox<span style=\"color: #BBB\"> <\/span>height<span style=\"color: #666\">=<\/span><span style=\"color: #BA2121\">\"1\"<\/span><span style=\"color: #BBB\"> <\/span>width<span style=\"color: #666\">=<\/span><span style=\"color: #BA2121\">\"1\"<\/span><span style=\"color: #BBB\"> <\/span>x<span style=\"color: #666\">=<\/span><span style=\"color: #BA2121\">\"0\"<\/span><span style=\"color: #BBB\"> <\/span>y<span style=\"color: #666\">=<\/span><span style=\"color: #BA2121\">\"0\"<\/span><span style=\"color: #BBB\"> <\/span><span style=\"color: #666\">\/&gt;<\/span>\n<span style=\"color: #BBB\">  <\/span><span style=\"color: #666\">&lt;<\/span>Complication<span style=\"color: #666\">&gt;<\/span><span style=\"color: #BBB\"> <\/span>\n\n<span style=\"color: #BBB\">    <\/span><span style=\"color: #666\"><!--<\/span><span style=\"color: #BBB\"> <\/span>Complication<span style=\"color: #BBB\"> <\/span>data<span style=\"color: #BBB\"> <\/span>source<span style=\"color: #BBB\"> <\/span>sends<span style=\"color: #BBB\"> <\/span><span style=\"color: #666\">3<\/span><span style=\"color: #BBB\"> <\/span>RGB<span style=\"color: #BBB\"> <\/span>hex<span style=\"color: #BBB\"> <\/span>values,<span style=\"color: #BBB\"> <\/span>extract<span style=\"color: #BBB\"> <\/span>the<span style=\"color: #BBB\"> <\/span>first:<span style=\"color: #BBB\"> <\/span><span style=\"color: #666\">--><\/span>\n<span style=\"color: #BBB\">    <\/span><span style=\"color: #666\">&lt;<\/span>PartDraw<span style=\"color: #BBB\"> <\/span>x<span style=\"color: #666\">=<\/span><span style=\"color: #BA2121\">\"0\"<\/span><span style=\"color: #BBB\"> <\/span>y<span style=\"color: #666\">=<\/span><span style=\"color: #BA2121\">\"0\"<\/span><span style=\"color: #BBB\"> <\/span>width<span style=\"color: #666\">=<\/span><span style=\"color: #BA2121\">\"1\"<\/span><span style=\"color: #BBB\"> <\/span>height<span style=\"color: #666\">=<\/span><span style=\"color: #BA2121\">\"1\"<\/span><span style=\"color: #666\">&gt;<\/span>\n<span style=\"color: #BBB\">      <\/span><span style=\"color: #666\">&lt;<\/span>Transform<span style=\"color: #BBB\"> <\/span>target<span style=\"color: #666\">=<\/span><span style=\"color: #BA2121\">\"tintColor\"<\/span><span style=\"color: #BBB\"> <\/span>value<span style=\"color: #666\">=<\/span><span style=\"color: #BA2121\">\"extractColorFromColors([COMPLICATION.TEXT], false, 0.0)\"<\/span><span style=\"color: #BBB\"> <\/span><span style=\"color: #666\">\/&gt;<\/span>\n<span style=\"color: #BBB\">      <\/span><span style=\"color: #666\">&lt;<\/span>Reference<span style=\"color: #BBB\"> <\/span>source<span style=\"color: #666\">=<\/span><span style=\"color: #BA2121\">\"tintColor\"<\/span><span style=\"color: #BBB\"> <\/span>defaultValue<span style=\"color: #666\">=<\/span><span style=\"color: #BA2121\">\"#000000\"<\/span><span style=\"color: #BBB\"> <\/span>name<span style=\"color: #666\">=<\/span><span style=\"color: #BA2121\">\"primary_color\"<\/span><span style=\"color: #BBB\"> <\/span><span style=\"color: #666\">\/&gt;<\/span>\n<span style=\"color: #BBB\">      <\/span><span style=\"color: #666\">&lt;<\/span>Line<span style=\"color: #BBB\"> <\/span>startX<span style=\"color: #666\">=<\/span><span style=\"color: #BA2121\">\"0\"<\/span><span style=\"color: #BBB\"> <\/span>startY<span style=\"color: #666\">=<\/span><span style=\"color: #BA2121\">\"0\"<\/span><span style=\"color: #BBB\"> <\/span>endX<span style=\"color: #666\">=<\/span><span style=\"color: #BA2121\">\"1\"<\/span><span style=\"color: #BBB\"> <\/span>endY<span style=\"color: #666\">=<\/span><span style=\"color: #BA2121\">\"1\"<\/span><span style=\"color: #666\">&gt;<\/span>\n<span style=\"color: #BBB\">        <\/span><span style=\"color: #666\">&lt;<\/span>Stroke<span style=\"color: #BBB\"> <\/span>color<span style=\"color: #666\">=<\/span><span style=\"color: #BA2121\">\"#000000\"<\/span><span style=\"color: #BBB\"> <\/span>thickness<span style=\"color: #666\">=<\/span><span style=\"color: #BA2121\">\"1\"<\/span><span style=\"color: #BBB\"> <\/span><span style=\"color: #666\">\/&gt;<\/span>\n<span style=\"color: #BBB\">      <\/span><span style=\"color: #666\"\/>Line<span style=\"color: #666\">&gt;<\/span>\n<span style=\"color: #BBB\">    <\/span><span style=\"color: #666\"\/>PartDraw<span style=\"color: #666\">&gt;<\/span>\n\n<span style=\"color: #BBB\">    <\/span>...\n<span style=\"color: #BBB\">  <\/span><span style=\"color: #666\"\/>Complication<span style=\"color: #666\">&gt;<\/span>\n<span style=\"color: #666\"\/>ComplicationSlot<span style=\"color: #666\">&gt;<\/span>\n<\/pre>\n<\/div>\n<p>This snippet illustrates creating a very small <span style=\"color: #0d904f ;font-family: courier;\">ComplicationSlot<\/span>, which will simply serve as a pipeline for our data:<\/p>\n<p>Within the complication, a placeholder <span style=\"color: #0d904f ;font-family: courier;\">PartDraw<\/span> is created, and the <span style=\"font-family: courier;\"><a href=\"https:\/\/developer.android.com\/reference\/wear-os\/wff\/common\/attributes\/arithmetic-expression#extract-color-from-colors\" target=\"_blank\" rel=\"noopener\">extractColorFromColors()<\/a><\/span> function is used to transform the <span style=\"color: #0d904f ;font-family: courier;\">PartDraw<\/span> to the first color supplied by the complication. Using the <span style=\"color: #0d904f ;font-family: courier;\">Reference<\/span> element, this color value is then available to the rest of the watch face as <span style=\"color: #0d904f ;font-family: courier;\">[REFERENCE.primary_color]<\/span>.<\/p>\n<p>In the full example, two more <span style=\"color: #0d904f ;font-family: courier;\">PartDraw<\/span> elements are used to provide the <span style=\"color: #0d904f ;font-family: courier;\">secondary_color<\/span> and <span style=\"color: #0d904f ;font-family: courier;\">tertiary_color<\/span>, simply providing the <span style=\"color: #0d904f ;font-family: courier;\">0.5<\/span> and <span style=\"color: #0d904f ;font-family: courier;\">1.0<\/span> index to the <span style=\"color: #0d904f ;font-family: courier;\">extractColorFromColors<\/span> function instead of the <span style=\"color: #0d904f ;font-family: courier;\">0.0<\/span> value.<\/p>\n<p><a href=\"https:\/\/github.com\/garanj\/wfp-use-cases\" target=\"_blank\" rel=\"noopener\">Some of the samples<\/a> illustrate how you can share different data types beyond just colors, such as numeric values.<\/p>\n<h2><span style=\"font-size: x-large;\">Referencing complication data in the watch face<\/span><\/h2>\n<p>The <span style=\"color: #0d904f ;font-family: courier;\">primary_color<\/span>, <span style=\"color: #0d904f ;font-family: courier;\">secondary_color<\/span> and <span style=\"color: #0d904f ;font-family: courier;\">tertiary_color<\/span> values can now be used elsewhere on the watch face, both in expressions and in <a href=\"https:\/\/developer.android.com\/reference\/wear-os\/wff\/common\/transform\/transform\" target=\"_blank\" rel=\"noopener\">transforms<\/a>. In our example, we use the colors on the watch face hands:<\/p>\n<p><!-- Kotlin --><\/p>\n<div style=\"background: #f8f8f8; overflow:auto;width:auto;border:0;\">\n<pre style=\"margin: 0; line-height: 125%;\"><span\/><span style=\"color: #666\">&lt;<\/span>HourHand<span style=\"color: #BBB\"> <\/span>resource<span style=\"color: #666\">=<\/span><span style=\"color: #BA2121\">\"hour\"<\/span><span style=\"color: #BBB\"> <\/span>x<span style=\"color: #666\">=<\/span><span style=\"color: #BA2121\">\"210\"<\/span><span style=\"color: #BBB\"> <\/span>y<span style=\"color: #666\">=<\/span><span style=\"color: #BA2121\">\"75\"<\/span><span style=\"color: #BBB\"> <\/span>width<span style=\"color: #666\">=<\/span><span style=\"color: #BA2121\">\"30\"<\/span><span style=\"color: #BBB\"> <\/span>height<span style=\"color: #666\">=<\/span><span style=\"color: #BA2121\">\"180\"<\/span><span style=\"color: #BBB\"> <\/span>pivotX<span style=\"color: #666\">=<\/span><span style=\"color: #BA2121\">\"0.5\"<\/span>\n<span style=\"color: #BBB\">    <\/span>pivotY<span style=\"color: #666\">=<\/span><span style=\"color: #BA2121\">\"0.8333\"<\/span><span style=\"color: #BBB\"> <\/span>tintColor<span style=\"color: #666\">=<\/span><span style=\"color: #BA2121\">\"[REFERENCE.primary_color]\"<\/span><span style=\"color: #666\">&gt;<\/span>\n<span style=\"color: #666\"\/>HourHand<span style=\"color: #666\">&gt;<\/span>\n\n<span style=\"color: #3D7B7B; font-style: italic\">\/\/ Similar logic for the minute hand and second hand would refer to<\/span>\n<span style=\"color: #3D7B7B; font-style: italic\">\/\/ secondary_color and tertiary_color, respectively.<\/span>\n<\/pre>\n<\/div>\n<h2><span style=\"font-size: x-large;\">Keeping the watch face package up to date<\/span><\/h2>\n<p>A challenge with the default watch face approach is that if the app is updated, the watch face doesn\u2019t automatically get updated with it, even if the new app bundle contains an updated watch face. To address that issue, the app uses a <span style=\"color: #0d904f ;font-family: courier;\">BroadcastReceiver<\/span> to receive the <span style=\"font-family: courier;\"><a href=\"https:\/\/developer.android.com\/reference\/android\/content\/Intent#ACTION_MY_PACKAGE_REPLACED\" target=\"_blank\" rel=\"noopener\">MY_PACKAGE_REPLACED<\/a><\/span> action. On receiving this, the app can then check whether the watch face is installed and is in need of an upgrade, using Watch Face Push to perform the upgrade if necessary.<\/p>\n<p>For the <span style=\"color: #0d904f ;font-family: courier;\">MY_PACKAGE_REPLACED<\/span> action to be received, the app must have been run at least once. For this reason, the sample watch faces include an example of ensuring the user launches the app: A \u201claunch app\u201d button is shown on the watch face if the app has not been launched before. This is achieved by using a <span style=\"color: #0d904f ;font-family: courier;\">Condition<\/span> on the <span style=\"color: #0d904f ;font-family: courier;\">CONFIGURED<\/span> or <span style=\"color: #0d904f ;font-family: courier;\">NOT_CONFIGURED<\/span> status described earlier.<\/p>\n<p>For many watch faces, this has an additional purpose: it allows the user to enable additional components, such as a photo downloader in the Photo Album example shown here. You can also use the \u201cfirst launch\u201d experience to prompt the user to grant permissions or to sign in.<\/p>\n<p><image><\/p>\n<div style=\"text-align: center;\"><img decoding=\"async\" alt=\"three side-by-side watch faces illistrating the supporting download service from the watch face\" border=\"0\" id=\"imgCaption\" src=\"https:\/\/blogger.googleusercontent.com\/img\/b\/R29vZ2xl\/AVvXsEhKb3Ll074jHXN1uea8zYLh6V-FM-blqQEkizU8-eL-mc2PAkQZ2GfX5OQWc__eeEqGEQc9lpaSJAc3PO16C9-jF_CMbUNgSpJUEosLG1SUYXOCdzr4k-10qBqLJotGI8Rxy2kNiDvNhWOMCtAkaVRhYa1phLtHWW-y4dr93P9boLxGjacFsVopsxz74yk\/s1600\/enabling-supporting-download-service-watch-face-push.png\" width=\"90%\"\/><\/div>\n<p><imgcaption><center><em>Enabling the supporting download service from the watch face<\/em><\/center><\/imgcaption><\/image><\/p>\n<h2><span style=\"font-size: x-large;\">Working with other app components<\/span><\/h2>\n<p>While the complication data source is the conduit for data, and is the common component in all the examples, the following Android APIs work with complications to achieve the desired functionality:<\/p>\n<ul>\n<ul>\n<li><span style=\"font-family: courier;\"><a href=\"https:\/\/developers.google.com\/android\/reference\/com\/google\/android\/gms\/wearable\/WearableListenerService\" target=\"_blank\" rel=\"noopener\">WearableListenerService<\/a><\/span> &#8211; both the <b>PaletteWatchFace<\/b> and the <b>FootballWatchFace<\/b> have phone companion apps, and the <a href=\"https:\/\/developer.android.com\/training\/wearables\/data\/data-items\" target=\"_blank\" rel=\"noopener\">Data Layer<\/a> is used to send data to the watch. Once received by the <span style=\"color: #0d904f ;font-family: courier;\">WearableListenerService<\/span>, you can proactively update the data on the watch face using <span style=\"font-family: courier;\"><a href=\"https:\/\/developer.android.com\/reference\/androidx\/wear\/watchface\/complications\/datasource\/ComplicationDataSourceUpdateRequester\" target=\"_blank\" rel=\"noopener\">ComplicationDataSourceUpdateRequester<\/a><\/span>.<\/li>\n<li><span style=\"font-family: courier;\"><a href=\"https:\/\/developer.android.com\/develop\/background-work\/background-tasks\/persistent\/getting-started\" target=\"_blank\" rel=\"noopener\">WorkManager<\/a><\/span> &#8211; the <b>PhotoAlbumWatchFace<\/b> example demonstrates how to retrieve photos from an online photo service. <span style=\"color: #0d904f ;font-family: courier;\">WorkManager<\/span> is used for this, using <span style=\"color: #0d904f ;font-family: courier;\">Constraints<\/span> to only download images while the device is being charged.<\/li>\n<li><span style=\"font-family: courier;\"><a href=\"https:\/\/developer.android.com\/develop\/background-work\/services\/fgs\" target=\"_blank\" rel=\"noopener\">ForegroundService<\/a><\/span> &#8211; the <b>DeviceDataWatchFace<\/b> illustrates using a <span style=\"color: #0d904f ;font-family: courier;\">ForegroundService<\/span> to obtain data from a connected Bluetooth device which is then visualized on the watch face.<\/li>\n<\/ul>\n<\/ul>\n<p><\/p>\n<p><image><\/p>\n<div style=\"text-align: center;\"><img decoding=\"async\" alt=\"samples made using WFP\" border=\"0\" id=\"imgCaption\" src=\"https:\/\/blogger.googleusercontent.com\/img\/b\/R29vZ2xl\/AVvXsEg9hPoEMQhoOUSubWVgO-U3FPA17XPYAfWC0TTYoNJu74a2hXCiWBrRM-jacwcSbAMh8smzUt_oh2lk1MpicWicpLKpB4nhPNVfOAv5-m9r1eIe_5ScQbRRuUDbNYnup4pa5z382RJpf_-VRWD1zd58Gi9AOm6ou5HAw7HBRBBFtqEGQ5zIuPJW76vUBSQ\/s1600\/watch-face-push.png\" width=\"100%\"\/><\/div>\n<p><imgcaption><center><em>Additional samples made using WFP, starting top left: Photo Album, Surfing, Connected Device, and Football Team watch faces<\/em><\/center><\/imgcaption><\/image><\/p>\n<p>Check out the <a href=\"https:\/\/github.com\/garanj\/wfp-use-cases\" target=\"_blank\" rel=\"noopener\">full source for these examples<\/a>. We look forward to seeing what you can create!<\/p>\n<\/div>\n<p>[ad_2]<br \/>\n<br \/><a href=\"http:\/\/android-developers.googleblog.com\/2025\/08\/further-explorations-with-watch-face-push.html\">Source link <\/a><\/p>\n","protected":false},"excerpt":{"rendered":"<p>[ad_1] Posted by Garan Jenkin \u2013 Developer Relations Engineer This post is part of Wear OS Spotlight Week. Today, we&#8217;re exploring the wonderful world of<\/p>\n","protected":false},"author":1,"featured_media":348483,"comment_status":"closed","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"_monsterinsights_skip_tracking":false,"_monsterinsights_sitenote_active":false,"_monsterinsights_sitenote_note":"","_monsterinsights_sitenote_category":0,"_uf_show_specific_survey":0,"_uf_disable_surveys":false,"footnotes":""},"categories":[146],"tags":[],"_links":{"self":[{"href":"https:\/\/michigandigitalnews.com\/index.php\/wp-json\/wp\/v2\/posts\/348482"}],"collection":[{"href":"https:\/\/michigandigitalnews.com\/index.php\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/michigandigitalnews.com\/index.php\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/michigandigitalnews.com\/index.php\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/michigandigitalnews.com\/index.php\/wp-json\/wp\/v2\/comments?post=348482"}],"version-history":[{"count":0,"href":"https:\/\/michigandigitalnews.com\/index.php\/wp-json\/wp\/v2\/posts\/348482\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/michigandigitalnews.com\/index.php\/wp-json\/wp\/v2\/media\/348483"}],"wp:attachment":[{"href":"https:\/\/michigandigitalnews.com\/index.php\/wp-json\/wp\/v2\/media?parent=348482"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/michigandigitalnews.com\/index.php\/wp-json\/wp\/v2\/categories?post=348482"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/michigandigitalnews.com\/index.php\/wp-json\/wp\/v2\/tags?post=348482"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}