Register now for Android Dev Summit 2019!

데이터를 정보 표시에 노출

시계 모드 정보 표시에는 데이터 제공자가 제공하는 데이터가 표시됩니다. 데이터 제공자는 텍스트, 문자열, 이미지 및 숫자가 포함된 원시 필드를 시계 모드에 제공합니다.

데이터 제공자 서비스는 사용자에게 유용한 정보를 시계 모드에 직접 전달하기 위해 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_OK 또는 RESULT_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 클래스에서 빌더를 사용하여 이러한 시간 종속 값을 만들 수 있습니다.