Wear OS 6 introduces a new API, Watch Face Push, which creates opportunities for
more advanced watch face publishing use cases.

## Identify when to use Watch Face Push

Watch Face Push is an API on Wear OS that allows the developer to add, update,
or remove watch faces directly. It isn't needed for standard watch face
development.

Watch faces used with Watch Face Push must be written using the Watch Face
Format. This can include watch faces designed using Watch Face Designer,
Watch Face Studio, or any other tool that produces watch faces that use the
Watch Face Format.

While the Watch Face Push API can potentially be used in a number of ways, the
following table should be used as a guide for the main use cases:

|                                                                                       Use case                                                                                        |                                                            Recommended solution                                                             | Complexity |
|---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|---------------------------------------------------------------------------------------------------------------------------------------------|------------|
| I want to create individual watch faces and publish them.                                                                                                                             | Use Watch Face Format, either directly or through a tool such as Watch Face Designer or Watch Face Studio, and publish them on Google Play. | Low        |
| I want to create a phone app that allows users to select watch faces from a curated collection, or design and customize watch faces for installation directly on their Wear OS watch. | Create an app, for both watch and phone, using the Watch Face Push API on the watch.                                                        | High       |

## Purpose

The canonical use case for the Watch Face Push API is for creating a
*marketplace* app. From this app, users can select watch faces from a curated
collection on their phone, and directly control the installation of these watch
faces onto their connected watch.

## Considerations

For details on building your watch faces, consult the [Watch Face Format](https://developer.android.com/training/wearables/wff)
guidance: Watch faces deployed using Watch Face Push are regular Watch Face
Format watch faces.

When building your watch face, keep the following considerations in mind.

### Package names

Watch faces installed using Watch Face Push must conform to the following
convention:

`<app name>.watchfacepush.<watchface name>`

... where `<app name>` is the package name of the app calling the Watch Face
Push API.

For example, for an app with package name `com.example.mymarketplace`, the
following are valid watch face package names:

- `com.example.mymarketplace.watchfacepush.watchface1`
- `com.example.mymarketplace.watchfacepush.watchface2`
- `com.example.mymarketplace.watchfacepush.another_watchface`

Watch faces that don't conform with this convention are rejected by the API.

### Package contents

The APK contents are strictly enforced. Care needs to be taken to ensure the
Watch Face Format conforms with the following constraints: It is technically
possible to produce Watch Face Format APKs that contain innocuous metadata
files and other artifacts, which might be acceptable to Google Play but don't
pass the Watch Face Push validation (see below).

Only the following files/paths are acceptable in each watch face APK:

- `/AndroidManifest.xml`
- `/resources.arsc`
- `/res/**`
- `/META-INF/**`

Additionally, only the following tags are permitted in the `AndroidManifest.xml`
file:

- `<manifest>`
- `<uses-feature>`
- `<uses-sdk>`
- `<application>`
- `<property>`
- `<meta-data>`

Finally, the package should specify a `minSdk` of at least `33`, and the
`<application>` tag should specify the attribute `android:hasCode="false"`.

### Validation

Unlike with regular watch faces distributed through Google Play, Watch Face Push
checks to ensure that each watch face is well formed and performant are the
responsibility of the Marketplace app.

Google Play uses the following validation checks to verify the quality of each
watch face that uses Watch Face Push:

1. All watch faces installed or updated through the Watch Face Push API must pass the Watch Face Push validation tool.
2. Only the official validation tool may be used to generate *validation tokens* for use with the API.
3. The validation tool used must be up-to-date at the time of running the validation.
4. There is no requirement to re-validate an APK that has not changed. Tokens
   don't expire, even when the version of the validation tool used is
   superseded.

   At the same time, we recommend that you re-run the validation once in a
   while, because the validator is updated periodically.

#### Run the validator

The validator is available in three forms:

- A CLI tool
- A library for use with the JVM
- A library for use on Android

#### Command-line validator usage

1. Obtain the validator from Google's [Maven repository](https://maven.google.com/web/index.html#com.google.android.wearable.watchface.validator:validator-push-cli).
2. Run the tool as follows:

       java -jar validator-push-cli-1.0.0-alpha07.jar \
           --apk_path=<your watch face>.apk \
           --package_name=<your marketplace package name>

   If successful, the output includes a *validation token*, which you must
   supply to the Watch Face Push API when adding or updating a watch face.

   If an error occurs, the output includes details about which particular
   check failed.

#### Library validator usage

1. Include the Jitpack repository, required for the validator dependency:

       repositories {
           ...
           google()
           maven {
               url = uri("https://jitpack.io")
               content {
                   includeGroup("com.github.xgouchet")
               }
           }
       }

2. Include the validator dependency in your project:

       // For use on JVM
       implementation("com.google.android.wearable.watchface.validator:validator-push:1.0.0-alpha07")

       // For use on Android
       implementation("com.google.android.wearable.watchface.validator:validator-push-android:1.0.0-alpha07")

3. Run the validator:

       val validator = DwfValidatorFactory.create()
       val result = validator.validate(watchFaceFile, appPackageName)

       if (result.failures().isEmpty()) {
           val token = result.validationToken()
           println("Validation token: $token")

           // Validation success - continue with the token
           // ...
       } else {
           // There were failures, handle them accordingly - validation has failed.
           result.failures().forEach { failure ->
               println("FAILURE: ${failure.name()}: ${failure.failureMessage()}")
               // ...
           }
       }  
       https://github.com/android/snippets/blob/1da1d9d645cd1a8e693981900e04d6bc32287a5c/watchfacepush/validator/src/main/kotlin/com/example/validator/Main.kt#L39-L54

For an example of using this library, see the [GitHub sample](https://github.com/android/wear-os-samples/tree/main/WatchFacePush). See also the
[Portable Asset Compiler Kit (Pack)](https://github.com/google/pack) library, which is useful for building
APKs on-device, for use with the Android-based validator.

### APK size

Particular care should be taken with Watch Face Push watch faces to ensure the
APK size is kept to a minimum: The watch face APK is likely to be transmitted
from the phone app to the watch app over Bluetooth, which can be slow.

An overly large APK could take a considerable time to transmit, which is both a
poor user experience and also draining on battery.

- Use appropriate libraries such as [`pngquant`](https://pngquant.org/) to keep image file sizes to a minimum
  - Include this in your watch face collection build process
  - Check dimensions of the image are appropriate for the scale at which it will be used.
  - Ensure images are appropriately cropped to remove any surrounding background.
- Reduce the size of font files
  - For example, if using a particular font only to show the time, in the format `HH:MM`, you can use a tool such as [`pyftsubset`](https://fonttools.readthedocs.io/en/stable/subset/) to limit the font file to only contain the necessary glyphs. This can dramatically reduce the size of the resulting font file and APK. [See
    this blog post for details on minimizing font file
    size](https://markoskon.com/creating-font-subsets/), for other cases.

Refer to the [Optimize memory usage guidance](https://developer.android.com/training/wearables/wff/memory-usage#methods) for further suggestions on
keeping APK size to a minimum.

### APK signing

As a regular APK, all your watch faces need signing. Create a
different key from that used with your main app and use the different key
for all your watch faces.

## Architecture

Consider the three main components of the system:

1. **Cloud-based storage** : In the canonical Marketplace app, your watch faces are built and stored in the Cloud, ready for use by your users. The watch faces are:
   1. Prebuilt as regular Watch Face Format APKs
   2. Each contain only a single Watch Face Format--based watch face
   3. Have been *validated* using the Watch Face Push validation process and are stored along with the associated validation token.
   4. Ready to be retrieved by your phone app as and when needed.
2. **Phone app** : The phone app is the main way in which your users interact with your system. It allows them to:
   1. Browse and search your catalog of watch faces
   2. Install or replace a watch face on the watch
3. **Watch app** : The watch app may typically not have a significant user interface. It is primarily a bridge between the phone app and the Watch Face Push APIs, with the following functionality:
   1. Using the Watch Face Push API to install/update or replace watch faces
   2. Requesting necessary permissions and prompting the user
   3. Providing a default watch face
   4. Providing a minimal cache of watch faces
4. **Phone-watch communications** : The phone and watch app communication is pivotal to the success of the overall experience. Use Wear OS Data Layer APIs, which allow:
   1. **Installation detection** : Using Capabilities and the [`CapabilityClient`](https://developers.google.com/android/reference/com/google/android/gms/wearable/CapabilityClient), the phone app can [detect the
      absence of the watch app](https://developer.android.com/training/wearables/apps/standalone-apps#detecting-your-app), and the other way around. This can be followed by launching an intent to the Play store to install the missing form factor.
   2. **State management** : Using the [`DataClient`](https://developers.google.com/android/reference/com/google/android/gms/wearable/DataClient) or [`MessageClient`](https://developers.google.com/android/reference/com/google/android/gms/wearable/MessageClient) the phone can be kept in sync with the state of the watch, for example, ensuring that the phone is aware of what watch face is set.
   3. **APK transmission** : Using [`ChannelClient`](https://developers.google.com/android/reference/com/google/android/gms/wearable/ChannelClient) or [`MessageClient`](https://developers.google.com/android/reference/com/google/android/gms/wearable/MessageClient), APKs can be sent from the phone to the watch
   4. **Remote invocation** : Using [`Messageclient`](https://developers.google.com/android/reference/com/google/android/gms/wearable/MessageClient), the phone can instruct the watch to call the Watch Face Push API, for example, to install a watch face.

Refer to [the Data Layer API guidance](https://developer.android.com/training/wearables/data/overview) for further details.