정보 표시에 데이터 노출

데이터 제공자 앱은 텍스트, 문자열, 이미지, 숫자를 포함한 필드를 제공하는 시계 모드 정보 표시에 정보를 노출합니다.

데이터 제공자 서비스는 ComplicationProviderService를 확장하여 유용한 정보를 시계 모드에 직접 전달합니다.

데이터 제공자 프로젝트 만들기

Android 스튜디오에서 데이터 제공자 앱용 프로젝트를 만들려면 다음 단계를 따르세요.

  1. File > New > New project를 클릭합니다.
  2. Create Android Project 창에서 기본값을 적용하고 Next를 클릭합니다.
  3. Target Android Devices 창에서 Wear 옵션만 선택하고, SDK 버전 목록에서 사용 가능한 최신 버전을 선택합니다. Next를 클릭합니다.
  4. Add an Activity to Wear 창에서 Add No Activity, Finish를 차례로 선택합니다.

    Android 스튜디오에서는 app 모듈을 사용하여 데이터 제공자용 프로젝트를 만듭니다. Android 스튜디오의 프로젝트에 관한 자세한 내용은 프로젝트 만들기를 참조하세요.

  5. BroadcastReceiver를 확장하는 새 클래스를 만들어 데이터 제공자 앱을 시작합니다. 클래스의 목적은 Wear OS 시스템의 정보 표시 업데이트 요청을 수신 대기하는 것입니다. 또한, 적절한 정보 표시 요청에 따라 실제로 데이터를 제공하기 위해 ComplicationProviderService를 확장하는 새 클래스를 만듭니다. 자세한 내용은 다음을 참조하세요.

    참고: 데이터 제공자에 활동을 추가할지 선택할 수 있습니다. 예를 들어, 사용자가 정보 표시를 탭할 때만 실행되는 활동을 추가할 수 있습니다.

업데이트 요청 메서드 구현

정보 표시 데이터가 필요한 경우 Wear OS 시스템이 데이터 제공자에게 업데이트 요청을 전송합니다. 요청은 BroadcastReceiver에서 수신합니다. 업데이트 요청에 응답하기 위해 데이터 제공자는 ComplicationProviderService 클래스의 onComplicationUpdate() 메서드를 구현해야 합니다. Wear OS 시스템은 제공자의 데이터가 필요한 경우 이 메서드를 호출합니다. 이러한 경우의 예로는 데이터 제공자를 사용하는 정보 표시가 활성 상태가 되는 경우 또는 정해진 시간이 경과한 경우를 들 수 있습니다. 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 = 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)
        }
    }
    

자바

    @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);
       }
    }
    

Manifest 선언 및 권한

데이터 제공자 앱은 앱 manifest에 특정 선언을 포함해야만 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>
    

메타데이터 요소 지정

매니페스트 파일에 다음 예와 같이 지원되는 유형과 업데이트 기간, 구성 작업을 지정하는 메타데이터를 포함합니다.

    <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_SECONDS0으로 설정하지 않으면 300(5분) 이상의 값을 사용해야 합니다. 이 값은 기기의 배터리 수명을 보존하기 위해 시스템에서 적용하는 최소 업데이트 기간입니다. 또한 기기가 대기 모드에 있거나 기기를 착용하지 않은 경우에는 업데이트 요청이 더 줄어들 수도 있습니다.

업데이트 전송에 관한 자세한 내용은 Wear API 참조 ComplicationProviderService 클래스와 관련해 나열된 키를 참조하세요.

구성 활동 추가

필요한 경우 제공자는 사용자가 데이터 제공자를 선택할 때 사용자에게 표시되는 구성 활동을 포함할 수 있습니다. 구성 활동을 포함하려면 다음 키와 함께 메타데이터 항목을 manifest의 제공자 서비스 선언에 포함하세요.

    <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를 사용하여 번인 안전 버전을 포함하세요.

푸시 업데이트 사용

앱 매니페스트에서 정보 표시가 지속적이며 1회 이상의 간격으로 업데이트되도록 지정하는 대신 ProviderUpdateRequester 인스턴스를 사용하여 동적으로 업데이트를 요청할 수 있습니다. 정보 표시의 사용자에게 표시되는 콘텐츠 업데이트를 요청하려면 onComplicationUpdate()를 호출합니다.

주의: 기기 배터리 수명을 보존하기 위해 ProviderUpdateRequester 인스턴스가 평균 5분 미만 간격으로 onComplicationUpdate()를 호출하면 안 됩니다.

시간 종속 값 제공

일부 정보 표시에는 현재 시간에 관련된 값이 표시되어야 합니다. 그 예로는 현재 날짜, 다음 미팅까지의 시간 또는 다른 시간대의 시간이 있습니다.

해당 값을 최신으로 유지하기 위해 매초 또는 매분마다 정보 표시를 업데이트하지 마세요. 정보 표시를 이렇게 자주 업데이트해서는 안 됩니다. 그 대신, 시간 종속 텍스트를 사용하여 현재 날짜나 시간에 상대적인 값을 지정하세요. ComplicationText 클래스에서 빌더를 사용하여 이러한 시간 종속 값을 만들 수 있습니다.