The Android Developer Challenge is back! Submit your idea before December 2.

정보 표시에 데이터 노출

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

데이터 제공자 서비스는 시계 모드에 유용한 정보를 직접 전달하기 위해 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 선언 및 권한

Android 시스템에 의해 데이터 제공자로 간주되기 위해서는, 데이터 제공자 앱이 특정 선언을 앱 manifest에 포함시켜야 합니다. 이 섹션에서는 데이터 제공자 앱의 필수 설정에 대해 설명합니다. 앱의 manifest에 서비스를 선언하고 업데이트 요청 액션 인텐트 필터를 추가합니다. 또한 Wear OS 시스템만이 제공자 서비스에 바인딩될 수 있도록 보장하기 위해 manifest가 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>
    

메타데이터 요소 지정

필요한 경우, 다음 예와 같이 지원되는 유형과 업데이트 기간 및 구성 액션을 지정하는 메타데이터를 manifest 파일에 포함합니다.

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

푸시 업데이트 사용

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

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

시간 종속 값 제공

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

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