設定 Wear OS 應用程式以便使用錶面推播功能

應用程式可透過錶面推送功能管理 Wear OS 裝置上的錶面。包括新增、更新及移除錶面,以及設定使用中錶面。設定 Wear OS 應用程式,使用 Watch Face Push API。

設定

build.gradle.kts 檔案中加入 androidx.wear.watchfacepush:watchfacepush 依附元件。

請將以下內容新增到 AndroidManifest.xml 中:

<!-- Required to use the Watch Face Push API.  -->
<uses-permission android:name="com.google.wear.permission.PUSH_WATCH_FACES" />

取得管理員例項的參照

取得 WatchFacePushManager 的執行個體:

val watchFacePushManager = WatchFacePushManagerFactory.createWatchFacePushManager(context)

WatchFacePushManager 可存取所有與錶面推送互動的方法。

使用運算單元

使用錶面推送功能時,插槽是重要概念。應用程式安裝的錶面會使用「時段」來處理。系統會為市集設定運算單元數量上限;在 Wear OS 6 中,上限為 1。

更新或移除錶面時,系統會使用 slotId 識別要執行作業的錶面。

列出錶面

如要列出已安裝的錶面,請使用 listWatchFaces()

val response = watchFacePushManager.listWatchFaces()
val installedList = response.installedWatchFaceDetails
installedList.forEach {
    Log.i(TAG, "Installed watchface: ${it.packageName}")
}

val remainingSlots = response.remainingSlotCount
Log.i(TAG, "Remaining slots: $remainingSlots")

藉此判斷該空位是否可用,或新增其他錶面是否需要取代現有錶面。清單也會提供已安裝錶面的詳細資料。舉例來說,如要檢查是否已安裝特定錶面套件,請執行下列操作:

suspend fun isInstalled(packageName: String) = watchFacePushManager.listWatchFaces()
    .installedWatchFaceDetails.any { it.packageName == packageName }

新增錶面

如果 listWatchFaces 回應指出有空位,則應使用 addWatchFace() 方法:

try {
    // Supply the validation token along with the watch face package data itself.
    val slot = watchFacePushManager.addWatchFace(parcelFileDescriptor, token)
    Log.i(TAG, "${slot.packageName} (${slot.versionCode}) added in slot ${slot.slotId}")
} catch (e: WatchFacePushManager.AddWatchFaceException) {
    Log.e(TAG, "Something went wrong installing the watch face", e)
}

更新錶面

更新錶面時,您可以將指定位置的內容替換為新套件。這可能是指將同一款錶面升級至較新版本,或是完全更換為其他錶面。

// Replacing the com.example.watchfacepush.green watch face with
// com.example.watchfacepush.red
val slotId =
    watchFacePushManager.listWatchFaces().installedWatchFaceDetails
        .firstOrNull { it.packageName == "com.example.watchfacepush.green" }?.slotId
        ?: throw IllegalArgumentException("No green watch face found")
try {
    watchFacePushManager.updateWatchFace(slotId, redParcelFileDesc, redValidationToken)
} catch (e: WatchFacePushManager.UpdateWatchFaceException) {
    Log.e(TAG, "Something went wrong updating the watch face", e)
}

移除錶面

如要移除錶面,請按照下列步驟操作:

// Remove the com.example.watchfacepush.green watch face.
val slotId =
    watchFacePushManager.listWatchFaces().installedWatchFaceDetails
        .firstOrNull { it.packageName == "com.example.watchfacepush.green" }?.slotId
        ?: throw IllegalArgumentException("No green watch face found")

try {
    watchFacePushManager.removeWatchFace(slotId)
} catch (e: WatchFacePushManager.RemoveWatchFaceException) {
    Log.e(TAG, "Something went wrong removing the watch face", e)
}

採用這種做法後,系統錶面挑選器一律會顯示您的錶面。你可以醒目顯示標誌,甚至顯示按鈕,讓使用者在手機上啟動 Marketplace 應用程式。

確認錶面是否處於啟用狀態

判斷市集是否已設定啟用中的錶面,有助於提供流暢的使用者體驗:如果市集已設定啟用中的錶面,使用者只要透過市集應用程式更換目前的錶面,即可選擇其他錶面。不過,如果市集沒有設定中的動態錶面,手機應用程式就必須提供更多指引。如要進一步瞭解如何處理這類使用者體驗,請參閱手機應用程式一節。

如要判斷市集是否已設定啟用中的錶面,請使用以下邏輯:

suspend fun hasActiveWatchFace() = watchFacePushManager.listWatchFaces()
    .installedWatchFaceDetails
    .any {
        watchFacePushManager.isWatchFaceActive(it.packageName)
    }

提供預設錶面

安裝市集應用程式時,錶面推送功能可安裝預設錶面。這項操作本身不會將該預設錶面設為使用中錶面 (請參閱設定使用中錶面),但會讓錶面顯示在系統錶面挑選器中。

如何使用這項功能:

  1. 在 Wear OS 應用程式版本中,將預設錶面納入路徑: assets/default_watchface.apk
  2. AndroidManifest.xml 中新增下列項目

    <meta-data
        android:name="com.google.android.wearable.marketplace.DEFAULT_WATCHFACE_VALIDATION_TOKEN"
        android:value="@string/default_wf_token" />

設定使用中的錶面

透過錶面推送功能,市集應用程式可以設定使用中的錶面。

具體來說,如果目前使用的錶面不屬於 Marketplace,應用程式可以將 Marketplace 的錶面設為使用中錶面。請注意,如果市集已提供使用中的錶面,則可透過呼叫 updateWatchFace,將錶面插槽的內容替換成其他錶面,藉此變更錶面。

設定使用中的錶面分為兩個階段:

  1. 取得設定使用中錶面所需的 Android 權限。
  2. 呼叫 setWatchFaceAsActive 方法。

取得設定使用中錶面的權限

必要權限為 SET_PUSHED_WATCH_FACE_AS_ACTIVE,必須新增至資訊清單:

<!-- Required to be able to call the setWatchFaceAsActive() method. -->
<uses-permission android:name="com.google.wear.permission.SET_PUSHED_WATCH_FACE_AS_ACTIVE" />

由於這是執行階段權限,應用程式執行時必須向使用者要求這項權限 (建議使用 Accompanist 程式庫來協助處理)。

將錶面設為使用中

授予權限後,請在應啟用的錶面 slot ID 上呼叫 setWatchFaceAsActive

一旦使用這個方法,手機應用程式就應改為提供手動設定啟用中錶面的指引。

從錶面 APK 讀取其他中繼資料

WatchFaceSlot 物件也提供取得其他資訊的方法,您可以在錶面上宣告這些資訊。

如果您有相同錶面的次要變體,這項功能就特別實用。舉例來說,您可以定義錶面,如下所示:

  • Package name:com.myapp.watchfacepush.mywatchface
  • 套件版本:1.0.0

但這個錶面可能以四個不同的 APK 形式提供,這些 APK 幾乎完全相同,但預設顏色不同:紅色、黃色、綠色藍色,這些顏色是在錶面格式 XML 的 ColorConfiguration 中設定。

這項微小差異會反映在四個 APK 中:

<!-- For watch face com.myapp.watchfacepush.mywatchface -->
<property
    android:name="default_color"
    android:value="red" />

應用程式可使用自訂屬性判斷安裝的是哪個變體:

val color = watchFaceDetails
    .getMetaData("com.myapp.watchfacepush.mywatchface.default_color")
    .invoke()
Log.i(TAG, "Default color: $color")

注意事項

在應用程式中導入錶面推送功能時,請特別注意耗電量、快取、更新隨附錶面,以及提供代表性的預設錶面。

電源

在 Wear OS 上執行的應用程式,耗電量是重要的考量因素。針對市集應用程式的 Wear OS 元件:

  1. 應用程式應盡可能減少執行次數和頻率 (除非使用者直接與應用程式互動)。包括:
    • 盡量減少從手機應用程式喚醒應用程式的情況
    • 盡量減少 WorkManager 工作執行次數
  2. 安排在手錶充電時產生數據分析報表
    1. 如要回報 Wear OS 應用程式的使用統計資料或其他指標,請使用 WorkManager 和 requiresCharging 限制。
  3. 在手錶充電時透過 Wi-Fi 安排更新
    1. 建議你檢查已安裝的錶面版本,並自動更新。同樣地,請使用 requiresCharging 限制和 UNMETERED 網路類型做為 requiresNetworkType
    2. 裝置充電時通常會連上 Wi-Fi。要求使用 Wi-Fi 快速下載更新版 APK,完成後釋放網路。
    3. 如果市集提供每日錶面,也請在手錶充電時預先下載。
  4. 請勿排定作業來檢查有效錶面
    1. 定期檢查市集是否仍有有效的錶面,以及是哪個錶面,會消耗電池電量。請避免使用這種方法。
  5. 不要在手錶上使用通知
    1. 如果應用程式會使用通知,請將通知重點放在手機上,讓使用者透過操作開啟手機應用程式,繼續完成流程。使用 setLocalOnly 設定通知,避免通知跨裝置傳送至手錶應用程式。

快取

在標準市集範例中,錶面會從手機轉移到手錶。這類連線通常是藍牙連線,速度可能相當緩慢。

為提供更優質的使用者體驗,並節省重新傳輸的電力,建議在 Wear OS 裝置中實作小型快取,儲存少量 APK。

如果使用者嘗試使用其他錶面,但後來決定恢復為先前選擇的錶面,這項操作幾乎是即時完成。

同樣地,這項功能可用於預先快取每日錶面或類似的配置,在 Wear OS 裝置充電時下載錶面。

更新隨附的錶面

如上所述,您的應用程式可能包含預設錶面資產。請務必瞭解,雖然安裝市集應用程式時,系統會安裝這個錶面,但如果市集應用程式更新時一併提供新版錶面,系統不會更新錶面。

為處理這種情況,市集應用程式應監聽 MY_PACKAGE_REPLACED 廣播動作,並檢查是否需要更新套件資產中的任何隨附錶面。

代表性的預設錶面

預設錶面是協助使用者探索及使用市集的好方法:安裝市集時會一併安裝錶面,因此使用者可以在錶面庫中找到。

使用預設錶面時,請注意以下事項:

  • 如果使用者選擇從市集應用程式解除安裝錶面,請勿使用 removeWatchFace。在這種情況下,請改用 updateWatchFace 將錶面還原為預設錶面。這有助於使用者在錶面庫中找到並設定你的錶面。
  • 透過標誌和主題設定,讓預設錶面簡單易辨。方便使用者在錶面庫中找到。
  • 在預設錶面上新增按鈕,即可開啟電話應用程式。這項操作可分兩個階段完成:

    1. 在錶面中新增 Launch 元素,透過 Wear OS 應用程式啟動意圖,例如:

      <Launch target="com.myapp/com.myapp.LaunchOnPhoneActivity" />

    2. LaunchOnPhoneActivity 中,使用 RemoteActivityHelper 啟動電話應用程式。