ウォッチフェイスの追加機能へのデータの公開

ウォッチフェイスの追加機能は、データ プロバイダから提供されたデータを表示します。データ プロバイダは、テキスト、文字列、イメージ、数値を含む生のデータ項目をウォッチフェイスに提供します。

データ プロバイダ サービスは、ComplicationProviderService を拡張したもので、便利な情報をユーザーのウォッチフェイスに直接提供します。

データ プロバイダ アプリの作成

ウォッチフェイスの追加機能データをアップデートする必要がある場合、Wear OS by Google はデータ プロバイダ アプリにアップデート リクエストを送信します。

システムからのアップデート リクエストに応答するために、データ プロバイダ アプリは ComplicationProviderService クラスの 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, we grab an incrementing number from SharedPrefs.
    val preferences = getSharedPreferences(
            ComplicationTapBroadcastReceiver.COMPLICATION_PROVIDER_PREFERENCES_FILE_KEY,
            0
    )

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

    when (dataType) {
        ComplicationData.TYPE_SHORT_TEXT ->
            ComplicationData.Builder(ComplicationData.TYPE_SHORT_TEXT)
                    .setShortText(ComplicationText.plainText(numberText))
                    .build().also { complicationData ->
                        complicationManager.updateComplicationData(complicationId, complicationData)
                    }
        else -> {
            if (Log.isLoggable(TAG, Log.WARN)) {
                Log.w(TAG, "Unexpected complication type $dataType")
            }
            // 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, we grab 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 システムがデータ プロバイダ アプリをデータ プロバイダとして扱えるようにするには、アプリ マニフェストに固有の宣言を含める必要があります。このセクションでは、データ プロバイダ アプリに必要な設定について説明します。アプリのマニフェストでサービスを宣言し、アップデート リクエストのアクション インテント フィルタを追加します。Wear OS システムだけがプロバイダ サービスにバインドできるように、マニフェストで BIND_COMPLICATION_PROVIDER パーミッションを追加してサービスを保護する必要もあります。

さらに、サービス要素には 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>

メタデータ要素の指定

マニフェスト ファイルには、必要に応じて、サポートされているタイプ、アップデート周期、設定操作を指定するメタデータを含めます。詳細については、Wear API リファレンスComplicationProviderService クラスに一覧が掲載されているキーをご覧ください。

UPDATE_PERIOD_SECONDS は、ウォッチフェイスの追加機能のデータ プロバイダがアクティブである場合、システムでデータのアップデートを確認する必要がある頻度を指定します。頻繁にアップデートを行うと電池寿命に影響する可能性があるので、この値にはできる限り長い時間を設定する必要があります。スケジュールによるアップデートが必要でない場合は、0 を指定します。なお、アップデート リクエストがこの頻度で送信されることが保証されるわけではないことに注意してください。システムは、最短のアップデート周期として 300 秒を適用します。また、端末が常に画面表示モードである場合や、端末を身につけていない場合は、アップデート リクエストの頻度が少なくなる場合があります。

または、固定のスケジュールでアップデートをリクエストするのではなく、アップデートの送信に「プッシュ型」を用いることもできます。必要に応じて、ProviderUpdateRequester を使って onComplicationUpdate を呼び出してください。次に例を示します。

            <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="0"/>

設定アクティビティの追加

必要に応じて、ユーザーがデータ プロバイダを選択したときに表示される設定アクティビティをプロバイダに含めることができます。設定アクティビティを含めるには、次のキーを持つメタデータ項目をマニフェストのプロバイダ サービス宣言に追加します。

          <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 というキーを持つメタデータを追加します。このメタデータの値は、カンマ区切りのリストである必要があります(空白は無視されます)。リスト内のエントリは、コンポーネント名(WatchFaceServices のコンポーネント名、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 を使って焼き付き防止版を追加します。

時間に依存する値の提供

ウォッチフェイスの追加機能の中には、現在時刻に関連する値を表示するものがあります。たとえば、現在の日付、次の打ち合わせまでの時間、別のタイムゾーンなどがあげられます。

これらの値を最新に保つために、ウォッチフェイスの追加機能を毎秒や毎分アップデートすることは避けてください。ウォッチフェイスの追加機能は、そのような頻度でアップデートするものではありません。代わりに、時間依存テキストを使って現在の日付や時間に対する相対値を指定します。ComplicationText クラスのビルダーを使用して、時間に依存する値を作成できます。