向小工具提供資料

資料供應商應用程式可為包含文字、字串、圖片和數字的欄位供應資料,藉此將資訊提供給錶面小工具

這項資料供應商服務擴充了 ComplicationProviderService 的功能,可將實用資訊直接提供給錶面。

建立資料供應商專案

如要在 Android Studio 為資料供應商應用程式建立專案,請完成下列步驟:

  1. 依序點選「File」>「New」>「New Project」
  2. 在「Project Template」視窗中按一下「Wear OS」分頁標籤,選取「No Activity」,然後點選「Next」
  3. 在「Configure Your Project」視窗中為專案命名,填寫標準專案資訊,然後按一下「Finish」
  4. Android Studio 會建立含有資料供應商應用程式模組的專案。如要進一步瞭解 Android Studio 中的專案,請參閱「建立專案」。
  5. 建立用於擴充 BroadcastReceiver 的新類別,啟動資料供應商應用程式。這個類別的用途是監聽 Wear OS 系統的小工具更新要求。此外,您也可以建立新類別來擴充 ComplicationProviderService,以便依據適當小工具的要求提供資料。如需詳細資訊,請參考下列資源:

    注意:您可以選擇是否要為資料供應商新增活動。舉例來說,您可能想要只有在使用者輕觸小工具時啟動的活動。

實作更新要求的方法

如果需要小工具資料,Wear OS 系統會向資料供應商傳送更新要求。要求會由您的 BroadcastReceiver 接收。如要回應更新要求,您的資料供應商必須實作 ComplicationProviderService 類別的 onComplicationUpdate() 方法。

Wear OS 系統會在需要供應商提供的資料時呼叫 onComplicationUpdate(),例如,當使用供應商的小工具開始運作時,或經過固定的一段時間後。系統會將 ComplicationManager 物件當做參數傳遞給 onComplicationUpdate,這可用於將資料傳回系統。

注意:資料供應商應用程式提供資料時,錶面會收到您傳送的原始值,因此可以繪製資訊。

下列程式碼片段顯示 onComplicationUpdate 方法的範本實作方式:

Kotlin

override fun onComplicationUpdate(
    complicationId: Int, dataType: Int, complicationManager: ComplicationManager) {

    Log.d(TAG, "onComplicationUpdate() id: $complicationId")

    // Used to create a unique key to use with SharedPreferences for this complication.
    val thisProvider = ComponentName(this, javaClass)

    // Retrieves your data; in this case, grabs an incrementing number from SharedPrefs.
    val preferences = getSharedPreferences(ComplicationTapBroadcastReceiver.COMPLICATION_PROVIDER_PREFERENCES_FILE_KEY, 0)

    val number = preferences.getInt(
            ComplicationTapBroadcastReceiver.getPreferenceKey(
                    thisProvider, complicationId),
                    0)
    val numberText = String.format(Locale.getDefault(), "%d!", number)

    var complicationData: ComplicationData? = null

    when (dataType) {
        ComplicationData.TYPE_SHORT_TEXT -> complicationData = ComplicationData.Builder(ComplicationData.TYPE_SHORT_TEXT)
                .setShortText(ComplicationText.plainText(numberText))
                .build()
        else -> if (Log.isLoggable(TAG, Log.WARN)) {
                    Log.w(TAG, "Unexpected complication type $dataType")
                }
    }

    if (complicationData != null) {
        complicationManager.updateComplicationData(complicationId, complicationData)
    } else {
        // If no data is sent, we still need to inform the ComplicationManager, so
        // the update job can finish and the wake lock isn't held any longer.
        complicationManager.noUpdateRequired(complicationId)
    }
}

Java

@Override
public void onComplicationUpdate(
       int complicationId, int dataType, ComplicationManager complicationManager) {

   Log.d(TAG, "onComplicationUpdate() id: " + complicationId);

   // Used to create a unique key to use with SharedPreferences for this complication.
   ComponentName thisProvider = new ComponentName(this, getClass());

   // Retrieves your data; in this case, grabs an incrementing number from SharedPrefs.
   SharedPreferences preferences =
     getSharedPreferences( ComplicationTapBroadcastReceiver.COMPLICATION_PROVIDER_PREFERENCES_FILE_KEY, 0);

   int number =
           preferences.getInt(
                   ComplicationTapBroadcastReceiver.getPreferenceKey(
                           thisProvider, complicationId),
                   0);
   String numberText = String.format(Locale.getDefault(), "%d!", number);

   ComplicationData complicationData = null;

   switch (dataType) {
       case ComplicationData.TYPE_SHORT_TEXT:
           complicationData =
                   new ComplicationData.Builder(ComplicationData.TYPE_SHORT_TEXT)
                           .setShortText(ComplicationText.plainText(numberText))
                           .build();
           break;
       default:
           if (Log.isLoggable(TAG, Log.WARN)) {
               Log.w(TAG, "Unexpected complication type " + dataType);
           }
   }

   if (complicationData != null) {
       complicationManager.updateComplicationData(complicationId, complicationData);

   } else {
       // If no data is sent, we still need to inform the ComplicationManager, so
       // the update job can finish and the wake lock isn't held any longer.
       complicationManager.noUpdateRequired(complicationId);
   }
}

資訊清單宣告和權限

資料供應商應用程式必須在應用程式資訊清單中加入特定宣告,Android 系統才會將其視為資料供應商。本節說明資料供應商應用程式的必要設定。

在應用程式的資訊清單中,宣告這項服務並新增更新要求動作的意圖篩選器。此外,資訊清單也必須透過新增 BIND_COMPLICATION_PROVIDER 權限來保護服務,確保只有 Wear OS 系統能繫結至供應商服務。

此外,請在提供單色白色圖示的 service 元素中加入 android:icon 屬性。建議您為圖示採用向量可繪項目。這個代表供應商的圖示會顯示在供應商選擇工具中。

範例如下:

<service
    android:name=".provider.IncrementingNumberComplicationProviderService"
    android:icon="@drawable/icn_complications"
    android:label="@string/complications_provider_incrementing_number"
    android:permission="com.google.android.wearable.permission.BIND_COMPLICATION_PROVIDER">
    <intent-filter>
        <action
         android:name="android.support.wearable.complications.ACTION_COMPLICATION_UPDATE_REQUEST"/>
    </intent-filter>
</service>

指定中繼資料元素

請在資訊清單檔案中納入中繼資料,以指定支援的類型、更新週期和設定動作,如以下範例所示:

<meta-data
    android:name="android.support.wearable.complications.SUPPORTED_TYPES"
    android:value="RANGED_VALUE,SHORT_TEXT,LONG_TEXT" />

<meta-data
    android:name="android.support.wearable.complications.UPDATE_PERIOD_SECONDS"
    android:value="300" />

顯示區資料供應應用程式啟用時,UPDATE_PERIOD_SECONDS 會指定您希望系統檢查資料更新的頻率。如果小工具中顯示的資訊不需要定期更新 (例如使用推送更新時),請將這個值設為 0

如果您未將 UPDATE_PERIOD_SECONDS 設為 0,必須使用至少 300 (5 分鐘) 的值,也就是系統強制執行的最低更新期限,來延長裝置的電池續航力。此外,請留意,裝置處於微光模式或沒有佩戴時,更新要求的頻率可能會降低。

如要進一步瞭解如何傳送更新,請參閱「Wear OS API 參考資料」中 ComplicationProviderService 類別所列的索引鍵。

新增設定活動

如有需要,供應商可納入設定活動,當使用者選擇資料供應商時,該活動就會向使用者顯示。如要納入設定活動,請在資訊清單的供應商服務宣告中加入中繼資料項目,並使用以下鍵:

<meta-data
    android:name="android.support.wearable.complications.PROVIDER_CONFIG_ACTION"
    android:value="PROVIDER_CONFIG_ACTION"/>

這個值可以是任何動作。

接著,使用意圖篩選器為該動作建立設定活動。設定活動必須與供應商位於同一套件中。設定活動必須傳回 RESULT_OKRESULT_CANCELED,讓系統知道是否應設定供應商。

供應商指定的安全錶面

供應商可以將特定錶面指定為「安全」,以便接收資料。只有在錶面嘗試將該供應商設為預設值,而該供應商也信任該錶面應用程式時,才能使用這個選項。

如要將錶面宣告為安全,供應商會以 android.support.wearable.complications.SAFE_WATCH_FACES 金鑰新增中繼資料。中繼資料值是以逗號分隔的 WatchFaceService 元件名稱清單 (如果呼叫的是 ComponentName.flattenToString()),或是應用程式套件名稱清單 (在此情況下,系統會將特定應用程式中的每個錶面都視為安全)。系統會忽略值清單中的空白字元。例如:

<meta-data
       android:name="android.support.wearable.complications.SAFE_WATCH_FACES"
       android:value="
          com.app.watchface/com.app.watchface.MyWatchFaceService,
          com.anotherapp.anotherwatchface/com.something.WatchFaceService,
          com.something.text"/>

提供防烙印圖片

在可能出現烙印情形的螢幕上,微光模式應避免使用純色區塊。如果您的圖示或圖片含有純色的區塊,也應提供防烙印版本。

使用 ComplicationData.Builder#setIcon 提供圖示時,請使用 ComplicationData.Builder#setBurnInProtectionIcon 加入防烙印版本。

使用 ComplicationData.Builder#setSmallImage 提供圖像時,請使用 ComplicationData.Builder#setBurnInProtectionSmallImage 加入防烙印版本。

使用推送更新

在應用程式資訊清單中,除了為小工具指定非零常數的更新間隔之外,也可以使用 ComplicationDataSourceUpdateRequester 的執行個體以動態方式要求更新。如要要求更新小工具的使用者可見內容,請呼叫 requestUpdate()

注意:為延長裝置電池續航力,透過 ComplicationDataSourceUpdateRequester 例項呼叫 requestUpdate() 的頻率不要超過平均每 5 分鐘一次。

提供動態價值

從 Wear OS 4 開始,部分小工具可顯示更頻繁地重新整理的值 進行管理。如要在 小工具,請使用 ComplicationData 欄位可接受 動態價值。這個平台會評估 系統會經常更新這些值,無需小工具供應程式執行。

範例欄位包括 GoalProgressComplicationData的動態值欄位,以及 DynamicComplicationText,可用於任何 ComplicationText 欄位。這些動態價值的計算依據 androidx.wear.protolayout.expression 程式庫。

在某些情況下,平台無法評估動態價值:

提供與時間對應的資料值

部分小工具需要顯示與目前時間相關的值。例如目前日期、距離下一場會議還有多少時間或其他時區的時間。

請勿為了讓資料保持最新狀態,設定每秒或每分鐘更新小工具。請改用時間相依文字,指定與目前日期或時間相關的值。您可以在 ComplicationText 類別中使用建構工具來建立這些時間相依值。

小工具更新率

您可能會想要快速更新小工具。不過,這可能會影響裝置的電池續航力。您可以選擇使用特殊權限的 Complication request API,提高特定小工具的更新頻率。不過,使用此 API 必須經手錶製造商允許。每一家手錶製造商都可決定哪些小工具能以高於一般允許的速率更新。