Wear OS에서 시계 화면 정보 표시에 데이터 노출

1. 정보 표시에 데이터 노출

이 Codelab에서는 정보 표시 데이터 소스를 빌드하는 방법을 알아봅니다.

개념 및 설정

Codelab을 마치면 Wear OS에서 시계 화면 정보 표시에 데이터를 제공하는 방법을 알 수 있습니다.

개념

정보 표시는 시간과 분 외에 시계 화면에서 제공하는 기능입니다. 예를 들어 아래 이미지의 시계 화면에는 네 가지 정보 표시가 있습니다.

39f4ebe8dc4800b0.png

Complications API는 시계 화면과 데이터 소스 앱에 모두 사용됩니다.

  • 정보 표시 데이터 소스는 배터리 수준, 날씨, 걸음 수 등의 데이터를 제공합니다.
  • 시계 화면 개발자는 이러한 데이터를 시계 화면의 정보 표시로 표시할 수 있습니다.
  • 사용자는 정보 표시로 원하는 데이터 소스를 선택합니다.

Screen Shot 2016-05-17 at 5.14.50 PM.png

이 Codelab에서는 정보 표시 데이터 소스 만들기를 알아봅니다. 시계 화면에 정보 표시를 추가하는 데도 관심이 있다면 시계 화면 샘플을 확인하세요.

그럼 시작해 볼까요?

시작 프로젝트 저장소 클론

빠르게 시작할 수 있도록 빌드할 프로젝트를 준비했습니다. Codelab에 필요한 몇 가지 기본 코드와 애플리케이션 설정이 포함되어 있습니다.

Git이 설치되어 있으면 아래 명령어를 실행합니다. 터미널/명령줄에 git --version을 입력하여 Git이 설치되어 있는지 확인하고 올바르게 실행되는지 확인할 수 있습니다.

 git clone https://github.com/android/codelab-complications-data-source.git

Git이 없으면 프로젝트를 ZIP 파일로 다운로드하면 됩니다.

프로젝트 가져오기

Android 스튜디오를 시작하고 시작 화면에서 Open an existing Android Studio project를 선택합니다. 프로젝트 디렉터리를 열고 complications-data-source 디렉터리에서 build.gradle 파일을 더블클릭합니다.

Android 뷰에 있으면 프로젝트 창 왼쪽 상단에 아래 스크린샷과 같은 폴더 아이콘 집합이 표시됩니다. Project 뷰에 있으면 complications-data-source 프로젝트를 펼쳐 폴더 아이콘 집합을 확인합니다.

786caabc75caee70.png

폴더 아이콘이 두 개 있습니다. 둘 다 모듈을 나타냅니다. Android 스튜디오에서 처음으로 프로젝트를 백그라운드에서 컴파일할 때는 몇 초 정도 걸릴 수 있습니다. 그동안 Android 스튜디오 하단의 상태 표시줄에 스피너가 표시됩니다.

27f04b5598a2f95e.png

Android 스튜디오가 필요한 모든 구성요소를 가져올 수 있도록 프로세스가 완료될 때까지 기다린 후 코드를 변경합니다.

시작 프로젝트 이해

설정이 완료되어 데이터를 정보 표시에 노출할 준비가 되었습니다. base 모듈부터 시작해 보겠습니다. 각 단계의 코드를 base에 추가합니다.

Codelab의 complete 모듈을 기준점으로 사용하여 작업을 확인하거나 문제가 발생하는 경우 참고합니다.

데이터 소스의 주요 구성요소 개요

  • ComplicationTapBroadcastReceiver: PendingIntent를 통해 정보 표시 데이터를 업데이트하는 데 사용되는 클래스입니다.
  • CustomComplicationDataSourceService: 정보 표시에 데이터를 노출하는 데 사용되는 클래스입니다. 파일은 base/java/com/example/android/wearable/complicationsdatasource 디렉터리에 있습니다. Android 스튜디오에서는 base/java/com.example.android.wearable.complicationsdatasource 아래에 있습니다. 클래스 내에서는 주로 네 가지 메서드를 작업합니다.
  • onComplicationActivated: 정보 표시가 데이터와 함께 활성화되었을 때 호출됩니다.
  • getPreviewData: 편집기 UI에서 사용되는 정보 표시의 미리보기 데이터입니다(일반적으로 정적 콘텐츠).
  • onComplicationRequest: 대부분의 작업이 이 메서드로 실행됩니다. 이 메서드는 활성 정보 표시에 소스의 업데이트된 데이터가 필요할 때마다 호출됩니다.
  • onComplicationDeactivated: 정보 표시가 비활성화되었을 때 호출됩니다.

에뮬레이터 설정

Wear OS 에뮬레이터를 설정하는 데 도움이 필요하다면 '웨어러블 앱 만들기 및 실행' 페이지의 에뮬레이터 실행 및 Wear 앱 실행 섹션을 참고하세요.

시작 프로젝트 실행

시계에서 앱을 실행해 보겠습니다.

  • Wear OS 기기를 연결하거나 에뮬레이터를 시작합니다.
  • 툴바의 드롭다운 선택기에서 'base' 구성을 선택하고 옆에 있는 녹색 삼각형(실행) 버튼을 클릭합니다.

a04699aa4cf2ca12.png

  • 아래와 같은 오류(Error Launching activity)가 발생하면 기본 실행 Activity를 변경합니다(아래 안내 참고). 6ea74bcba8278349.png

반대로 앱을 실행할 때 사용할 Activity를 묻는 메시지가 표시되면 Do not launch Activity를 선택합니다.

  • 필요한 경우 이전 단계의 기본 실행 Activity를 변경하려면 녹색 화살표 왼쪽에 있는 드롭다운 선택기를 클릭하고 edit configurations를 클릭합니다.

1e3e1dc73655ccd8.png

base를 선택하면 아래와 같은 창이 표시됩니다. Launch Options 섹션에서 Nothing을 선택하고 'Run'을 클릭합니다. 나중에 다른 모듈을 실행하려면 이 작업도 실행해야 합니다.

5e98572969d8228.png

  • Android 기기나 에뮬레이터를 선택하고 'OK'를 클릭합니다. 이렇게 하면 Wear OS 기기나 에뮬레이터에 서비스가 설치됩니다.
  • 몇 초 후 서비스가 빌드되고 배포할 준비가 됩니다. Android 스튜디오 하단의 상태 표시줄에 스피너가 표시됩니다.
  • Android 스튜디오 왼쪽 하단의 Build 탭에 아직 없다면 이 탭을 선택합니다. 그러면 설치 진행 상황을 확인할 수 있습니다. 설치 프로세스가 끝나면 Build: completed successfully라는 메시지가 표시됩니다.

5ea92276833c0446.png

  • 정보 표시를 선택할 수 있는 시계 화면을 선택합니다. 여기서는 Elements Digital을 선택했지만 개발자의 시계에는 제공되지 않을 수도 있습니다.

a5cf2c605206efe2.png

이번이 처음으로 이 시계 화면을 실행하는 것이므로 'Add more watch faces'에서 선택해야 합니다. 한 번 선택하면 이 옵션과 함께 옵션 중 하나로 표시됩니다.

  • 이제 즐겨찾기 메뉴에서 선택한 시계 화면이 중앙에 표시됩니다(아래 이미지 참고). 하단의 톱니바퀴 아이콘을 클릭합니다.

f17fb6b4cfe06182.png

  • 이 시계 화면의 경우 Data를 선택해야 합니다. 사용하고 있는 맞춤 시계 화면의 경우 UI가 다를 수 있습니다.

aef4fca32751a15a.png

  • 위치, 즉 +(정보 표시)를 선택합니다.

461f8a704fbc6496.png

  • 마지막으로 아래로 스크롤하여 Complications Data Source Codelab 서비스를 선택합니다. 선택한 후에는 왼쪽으로 여러 번 스와이프하거나 기기를 손바닥으로 만져 종료해야 할 수 있습니다.

b4d0d14140ce0120.png

  • 출력에는 'onComplicationActivated()' 및 'onComplicationRequest ()' 로그 메시지가 모두 표시됩니다. 그러나 정보 표시 위치에는 아무것도 표시되지 않습니다.
  • 로그 메시지가 표시되지 않으면 툴바에서 녹색 삼각형 버튼을 눌러 시계 화면을 다시 배포해 봅니다.
  • Log 데이터를 확인하는 방법을 잘 모른다면 Android 스튜디오 하단에서 6: Logcat 라벨이 붙은 탭을 클릭합니다. 드롭다운을 기기/에뮬레이터 및 패키지 이름 com.example.android.wearable.complicationsdatasource로 설정합니다(아래 스크린샷 참고).

af9cf164f9c598fc.png

선택한 데이터 슬롯에 아무것도 표시되지 않아도 걱정할 필요 없습니다. 아직 제공된 데이터가 없기 때문입니다. 다음 단계에서 데이터를 추가합니다.

일부 시계에서는 Elements 시계 화면에 정보 표시가 사용 설정되어 있으므로 시계에 채워진 정보 표시가 표시될 수 있습니다. 에뮬레이터에 비행기 아이콘 대신 취소선이 표시된 구름이 있어도 걱정하지 마세요. 이 Codelab에서는 휴대전화나 인터넷에 연결하지 않아도 됩니다.

52da39817e329e7a.png

요약

이 단계에서 알아본 내용은 다음과 같습니다.

  • Wear OS와 정보 표시에 데이터를 노출하는 개념
  • 시작점(base 모듈)에 관한 기본사항
  • 시계 화면 배포와 실행

다음 단계

일부 데이터를 노출해 보겠습니다.

2. Short Text 데이터 노출

코드 2단계

이 단계에서는 데이터 노출을 시작합니다. 정보 표시는 여러 유형의 데이터를 허용합니다. 이 단계에서는 Short Text 데이터 유형을 반환합니다.

언제라도 여기서 설명하는 개념이 어렵다면 complete 모듈을 참고하여 이러한 단계가 구현될 수 있는 방법을 알아보세요.

데이터 소스에서 지원하는 데이터 유형 지정

AndroidManifest.xml 파일을 열고 서비스 CustomComplicationDataSourceService를 확인합니다. 인텐트 필터에 유의하세요.

<action android:name=
    "android.support.wearable.complications.ACTION_COMPLICATION_UPDATE_REQUEST"/>

이는 서비스에서 ComplicationDataSourceServiceSuspendingComplicationDataSourceService(Kotlin 코루틴을 지원하는 변형)를 확장하고 정보 표시를 위해 데이터를 전송할 수 있다고 시스템에 알립니다.

다음은 Google에서 지원하는 데이터 유형을 지정하는 meta-data 요소입니다. 여기서는 SMALL_IMAGE가 지원되지만 이 단계에서는 SHORT_TEXT로 변경합니다. 첫 번째 meta-data 요소를 다음으로 변경합니다.

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

데이터 노출

앞서 언급했듯이 onComplicationActivated()는 데이터 소스가 활성화될 때 호출됩니다. 이는 활성화당 한 번 실행해야 하는 기본 설정을 실행하기에 좋은 위치/시간입니다. 이 Codelab에서는 이 작업을 하지 않습니다. 샘플이 비교적 간단하기 때문입니다.

onComplicationRequest() 호출은 활성 정보 표시가 업데이트된 데이터를 요청하는 위치입니다.

onComplicationRequest() 메서드는 다음과 같은 다양한 이유로 트리거됩니다.

  • 활성 시계 화면 정보 표시가 이 소스를 사용하도록 변경됩니다.
  • 이 소스를 사용하는 정보 표시가 활성화됩니다.
  • ComplicationDataSourceUpdateRequester.requestUpdate()ComplicationDataSourceUpdateRequester.requestUpdateAll()을 통해 자체 클래스에서 업데이트를 트리거했습니다.
  • 매니페스트에서 지정한 기간이 경과했습니다.

CustomComplicationDataSourceService .kt를 열고 커서를 onComplicationRequest() 메서드로 이동합니다. 'return null' 줄을 삭제하고 아래 코드를 복사하여 첫 번째 Log.d() 호출 아래에 붙여넣습니다.

// Retrieves your data, in this case, we grab an incrementing number from Datastore.
val number: Int = applicationContext.dataStore.data
    .map { preferences ->
        preferences[TAP_COUNTER_PREF_KEY] ?: 0
    }
    .first()

val numberText = String.format(Locale.getDefault(), "%d!", number)

여기서는 데이터를 나타내는 DataStore에서 저장된 int를 가져옵니다. 이는 쉽게 데이터베이스 호출이 될 수 있습니다.

DataStore와 상호작용하려면 생성하는 Flow 수집을 코루틴이 처리해야 합니다. onComplicationRequest()suspend 함수이므로 특별히 코루틴을 실행하지 않고도 Flow를 통해 데이터를 수집할 수 있습니다.

정수 값을 가져온 후 단순 문자열로 변환합니다. 이는 정보 표시에서 이해하는 데이터 유형인 ComplicationData 객체로 변환하기 위한 준비 단계입니다.

그런 다음 방금 추가한 코드 아래에 코드를 복사하여 붙여넣습니다.

return when (request.complicationType) {

    ComplicationType.SHORT_TEXT -> ShortTextComplicationData.Builder(
        text = PlainComplicationText.Builder(text = numberText).build(),
        contentDescription = PlainComplicationText
            .Builder(text = "Short Text version of Number.").build()
    )
        .build()

    else -> {
        if (Log.isLoggable(TAG, Log.WARN)) {
            Log.w(TAG, "Unexpected complication type ${request.complicationType}")
        }
        null
    }
}

이 코드에서는 정보 표시 유형에 기반하여 ComplicationData 객체를 반환합니다. 즉, 데이터 유형 SHORT_TEXTShortTextComplicationData(ComplicationData의 서브클래스)를 반환합니다.

지정된 데이터 유형에는 다양한 입력란이 포함될 수 있습니다. 예를 들어 SHORT_TEXT는 단일 텍스트거나 제목과 텍스트, 단색 이미지와 텍스트일 수 있습니다(모두 접근성을 위한 콘텐츠 설명을 포함해야 함).

여기서는 필수 입력란만 설정하고 선택 입력란은 설정하지 않습니다. 이러한 유형과 입력란에 관한 자세한 내용은 문서를 참고하세요.

when 문을 사용하여 데이터를 만드는 이유가 궁금할 수 있습니다. 이후에는 시스템에서 요청하는 유형에 따라 다양한 데이터 형식을 지원합니다. 지금 when 문을 사용함으로써 나중에 새 데이터 유형(LONG_TEXT, RANGED_VALUE 등)을 쉽게 추가할 수 있습니다.

마지막으로 데이터 유형이 지원되지 않으면 null이 반환됩니다.

최종 메서드는 다음과 같습니다.

override suspend fun onComplicationRequest(request: ComplicationRequest): ComplicationData? {
    Log.d(TAG, "onComplicationRequest() id: ${request.complicationInstanceId}")

    // Retrieves your data, in this case, we grab an incrementing number from Datastore.
    val number: Int = applicationContext.dataStore.data
        .map { preferences ->
            preferences[TAP_COUNTER_PREF_KEY] ?: 0
        }
        .first()

    val numberText = String.format(Locale.getDefault(), "%d!", number)

    return when (request.complicationType) {

        ComplicationType.SHORT_TEXT -> ShortTextComplicationData.Builder(
            text = PlainComplicationText.Builder(text = numberText).build(),
            contentDescription = PlainComplicationText
                .Builder(text = "Short Text version of Number.").build()
        )
            .build()

        else -> {
            if (Log.isLoggable(TAG, Log.WARN)) {
                Log.w(TAG, "Unexpected complication type ${request.complicationType}")
            }
            null
        }
    }
}

앱 다시 실행

첫 번째 단계에서는 기기나 에뮬레이터에 정보 표시 데이터 서비스를 설치하는 방법을 알아봤습니다. 이제 다시 한번 해 보겠습니다. 앱을 설치하고 정보 표시를 다시 선택합니다. 즉, 시계 화면을 스와이프하고 톱니바퀴를 선택한 후 같은 정보 표시로 이동하여 정보 표시 데이터 소스 Codelab을 선택합니다. 다음과 같이 표시됩니다.

caae484f1f2508fd.png

요약

이 단계에서 알아본 내용은 다음과 같습니다.

  • 소스에서 지원할 수 있는 데이터 유형을 지정하는 방법
  • 활성 정보 표시에서 사용하고 있을 때 데이터를 요청해야 하는 빈도
  • Wear OS에 데이터를 노출하는 위치

다음 단계

다른 데이터 유형을 지원해 보겠습니다.

3. 정보 표시 데이터 업데이트 트리거

코드 단계 3

이 단계에서는 사용자가 정보 표시를 탭할 때 데이터 업데이트를 트리거합니다.

언제라도 여기서 설명하는 개념이 어렵다면 complete 모듈을 참고하여 이러한 단계가 구현될 수 있는 방법을 알아보세요.

정보 표시에서 데이터를 새로고침해야 하는 빈도 지정

AndroidManifest.xml 파일을 열고 서비스 CustomComplicationDataSourceService를 다시 확인합니다.

meta-data 요소에서 UPDATE_PERIOD_SECONDS 입력란을 확인합니다. 데이터 소스가 활성 상태일 때 시스템에서 데이터 업데이트를 확인해야 하는 빈도를 지정합니다.

현재 600초(10분)로 설정되어 있습니다. 사용자 작업에 응답하여 정보 표시를 업데이트하려고 하므로 더 자주 업데이트해야 합니다. 이 기간을 줄일 수는 있지만 시스템에서는 기간이 2분이 안 되면 업데이트를 트리거하지 않을 수 있습니다.

더 나은 접근 방식은 데이터가 변경될 때 정확히 업데이트하라고 시스템에 지시하는 '푸시 스타일'입니다.

업데이트 빈도를 600에서 0으로 변경합니다. 이는 데이터가 변경될 때 정기 업데이트에 의존하는 대신 시스템을 직접 핑한다는 의미입니다. meta-data는 필수 항목입니다.

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

새 정보 표시 데이터를 사용할 수 있다고 시스템에 알림

ComplicationTapBroadcastReceiver.kt를 엽니다. 이 BroadcastReceiver 클래스는 정보 표시 데이터가 트리거되면 이를 업데이트합니다. 데이터는 DataStore에 저장됩니다.

이 클래스는 PendingIntent를 구성하는 도우미 메서드도 제공합니다(BroadcastReceiver로 트리거함).

현재 onReceive() 메서드는 인텐트에서 데이터 소스 및 정보 표시 ID를 추출하고 DataStore의 정수를 업데이트합니다. 정보 표시에 데이터가 업데이트되었다고 알려야 합니다.

onReceive() 메서드의 하단으로 이동합니다. finally 블록 위에 'Request an update for the...' 주석이 표시됩니다. 이 주석 아래에 코드를 복사하여 붙여넣습니다.

// Request an update for the complication that has just been tapped, that is,
// the system call onComplicationUpdate on the specified complication data
// source.
val complicationDataSourceUpdateRequester =
    ComplicationDataSourceUpdateRequester.create(
        context = context,
        complicationDataSourceComponent = dataSource
    )
complicationDataSourceUpdateRequester.requestUpdate(complicationId)

이는 Wear OS에 정보 표시 데이터가 업데이트되었다고 알립니다. 이 작업을 하려면 세 가지 데이터가 필요합니다.

  • context: ContextonReceive() 메서드의 인수로 사용할 수 있습니다.
  • complicationDataSourceComponent: 정보 표시의 DataSource는 이 BroadcastReceiver를 트리거하는 PendingIntent에서 Extra로 전달됩니다.
  • complicationId: 정보 표시 위치를 위해 시계 화면에서 할당된 고유한 정수입니다. int는 이 BroadcastReceiver를 트리거하는 PendingIntent에서 Extra로 전달됩니다.

이제 이 단계는 완료되었고 최종 메서드는 다음과 같습니다.

override fun onReceive(context: Context, intent: Intent) {

    // Retrieve complication values from Intent's extras.
    val extras = intent.extras ?: return
    val dataSource = extras.getParcelable<ComponentName>(EXTRA_DATA_SOURCE_COMPONENT) ?: return
    val complicationId = extras.getInt(EXTRA_COMPLICATION_ID)

    // Required when using async code in onReceive().
    val result = goAsync()

    // Launches coroutine to update the DataStore counter value.
    scope.launch {
        try {
            context.dataStore.edit { preferences ->
                val currentValue = preferences[TAP_COUNTER_PREF_KEY] ?: 0

                // Update data for complication.
                val newValue = (currentValue + 1) % MAX_NUMBER

                preferences[TAP_COUNTER_PREF_KEY] = newValue
            }

            // Request an update for the complication that has just been tapped, that is,
            // the system call onComplicationUpdate on the specified complication data
            // source.
            val complicationDataSourceUpdateRequester =
                ComplicationDataSourceUpdateRequester.create(
                    context = context,
                    complicationDataSourceComponent = dataSource
                )
            complicationDataSourceUpdateRequester.requestUpdate(complicationId)
        } finally {
            // Always call finish, even if cancelled
            result.finish()
        }
    }
}

정보 표시에 탭 작업 추가

BroadcastReceiver는 데이터를 업데이트할 뿐 아니라 시스템에 새 데이터를 사용할 수 있다고 알립니다(이전 단계 참고). BroadcastReceiver를 트리거하려면 정보 표시에 탭 작업을 추가해야 합니다.

CustomComplicationDataSourceService.kt를 열고 onComplicationRequest() 메서드로 이동합니다.

첫 번째 Log.d() 문 아래, Datastore에서 정수를 가져오는 위치 위에 아래 코드를 복사하여 붙여넣습니다.

// Create Tap Action so that the user can trigger an update by tapping the complication.
val thisDataSource = ComponentName(this, javaClass)
// We pass the complication id, so we can only update the specific complication tapped.
val complicationPendingIntent =
    ComplicationTapBroadcastReceiver.getToggleIntent(
        this,
        thisDataSource,
        request.complicationInstanceId
    )

이전 단계를 떠올려 보면 BroadcastReceiver가 작동하기 위해서는 이러한 데이터(데이터 소스, 정보 표시 ID)가 모두 필요했습니다. 여기서는 둘 다 PendingIntent를 사용하여 추가 항목으로 전달됩니다.

이제 PendingIntent를 정보 표시의 탭 이벤트에 할당해야 합니다.

ST의 when 문을 찾아 .build() 호출 위에 다음 줄을 추가합니다.

    .setTapAction(complicationPendingIntent)

코드 블록은 이제 다음과 같이 표시됩니다.

ComplicationType.SHORT_TEXT -> ShortTextComplicationData.Builder(
    text = PlainComplicationText.Builder(text = numberText).build(),
    contentDescription = PlainComplicationText
        .Builder(text = "Short Text version of Number.").build()
)
    .setTapAction(complicationPendingIntent)
    .build()

그러면 정보 표시의 탭 작업에 새 PendingIntent를 할당하는 .setTapAction() 메서드 한 줄만 추가됩니다.

이 단계는 완료되었습니다. 최종 메서드는 다음과 같습니다.

override suspend fun onComplicationRequest(request: ComplicationRequest): ComplicationData? {
    Log.d(TAG, "onComplicationRequest() id: ${request.complicationInstanceId}")

    // Create Tap Action so that the user can trigger an update by tapping the complication.
    val thisDataSource = ComponentName(this, javaClass)
    // We pass the complication id, so we can only update the specific complication tapped.
    val complicationPendingIntent =
        ComplicationTapBroadcastReceiver.getToggleIntent(
            this,
            thisDataSource,
            request.complicationInstanceId
        )

    // Retrieves your data, in this case, we grab an incrementing number from Datastore.
    val number: Int = applicationContext.dataStore.data
        .map { preferences ->
            preferences[TAP_COUNTER_PREF_KEY] ?: 0
        }
        .first()

    val numberText = String.format(Locale.getDefault(), "%d!", number)

    return when (request.complicationType) {

        ComplicationType.SHORT_TEXT -> ShortTextComplicationData.Builder(
            text = PlainComplicationText.Builder(text = numberText).build(),
            contentDescription = PlainComplicationText
                .Builder(text = "Short Text version of Number.").build()
        )
            .setTapAction(complicationPendingIntent)
            .build()

        else -> {
            if (Log.isLoggable(TAG, Log.WARN)) {
                Log.w(TAG, "Unexpected complication type ${request.complicationType}")
            }
            null
        }
    }
}

앱 다시 실행

앱을 설치하고 정보 표시를 다시 선택합니다. 즉, 시계 화면을 스와이프하고 톱니바퀴를 선택한 후 같은 정보 표시로 이동하여 정보 표시 데이터 소스 Codelab 소스를 선택합니다. 이전에 본 것과 같은 항목이 표시됩니다. 그러나 이제는 정보 표시를 탭할 수 있으므로 데이터가 업데이트됩니다.

a9d767e37161e609.png

요약

이 단계에서 알아본 내용은 다음과 같습니다.

  • 정보 표시 데이터가 업데이트되었다고 시스템에 알리는 방법
  • 정보 표시의 탭 작업에 PendingIntent를 연결하는 방법

다음 단계

다른 데이터 유형을 지원해 보겠습니다.

4. Long Text 데이터 노출

코드 단계 4

정보 표시에 데이터를 노출할 때 더 많은 데이터 유형을 지원하고 정보 표시에서 다양한 데이터 유형이 표시되는 모양을 확인하는 것이 좋습니다.

지원되는 다른 데이터 유형 지정

AndroidManifest.xml 파일을 다시 열고 서비스 CustomComplicationDataSourceService의 선언을 확인합니다.

meta-data 요소 SUPPORTED_TYPESSHORT_TEXT에서 LONG_TEXT로 변경합니다. 변경사항은 다음과 같이 표시됩니다.

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

LONG TEXT 지원 추가

CustomComplicationDataSourceService.kt를 열고 onComplicationRequest() 메서드의 when 문으로 이동한 후 다음 코드를 TYPE_SHORT_TEXT 사례의 끝부분 아래, 기본 사례 위에 추가합니다.

ComplicationType.LONG_TEXT -> LongTextComplicationData.Builder(
    text = PlainComplicationText.Builder(text = "Number: $numberText").build(),
    contentDescription = PlainComplicationText
        .Builder(text = "Long Text version of Number.").build()
)
    .setTapAction(complicationPendingIntent)
    .build()

when 문은 다음과 같이 표시됩니다.

return when (request.complicationType) {

    ComplicationType.SHORT_TEXT -> ShortTextComplicationData.Builder(
        text = PlainComplicationText.Builder(text = numberText).build(),
        contentDescription = PlainComplicationText
            .Builder(text = "Short Text version of Number.").build()
    )
        .setTapAction(complicationPendingIntent)
        .build()

    ComplicationType.LONG_TEXT -> LongTextComplicationData.Builder(
        text = PlainComplicationText.Builder(text = "Number: $numberText").build(),
        contentDescription = PlainComplicationText
            .Builder(text = "Long Text version of Number.").build()
    )
        .setTapAction(complicationPendingIntent)
        .build()

    else -> {
        if (Log.isLoggable(TAG, Log.WARN)) {
            Log.w(TAG, "Unexpected complication type ${request.complicationType}")
        }
        null
    }
}

같은 데이터를 새 형식으로 단순히 재구성한다는 사실을 알 수 있습니다. 어떻게 표시되는지 살펴보겠습니다.

진행 상황을 확인하고 디버그하는 방법

서비스를 설치하지만 이번에는 하단 슬롯 정보 표시를 선택한 후 정보 표시 서비스 소스를 선택합니다.

518b646d3c3f3305.png

아래와 같은 이미지가 표시됩니다. 각 정보 표시는 별도의 키로 저장되므로 여러 위치에서 정보 표시를 설정했다면 다양한 값이 표시될 수 있습니다.

17ec0506f1412676.png

요약

이 단계에서 알아본 내용은 다음과 같습니다.

  • 다양한 정보 표시 데이터 유형 변경 및 지원

다음 단계

모든 데이터를 합치기 전에 한 가지 추가 데이터 유형을 지원하려고 합니다.

5. Ranged Text 데이터 노출

코드 단계 5

데이터를 정보 표시에 노출하는 동안 더 많은 데이터 유형을 지원하는 방법을 계속 살펴보겠습니다.

지원되는 다른 데이터 유형 지정

AndroidManifest.xml 파일을 다시 열고 서비스 CustomComplicationDataSourceService를 확인합니다.

meta-data 요소 SUPPORTED_TYPESRANGED_VALUE로 변경합니다. 변경사항은 다음과 같이 표시됩니다.

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

RANGED VALUE 지원 추가

범위 지정 값은 텍스트를 표시할 뿐만 아니라 최솟값과 최댓값 사이의 값 차이를 보여주는 시각적 요소도 표시할 수 있습니다. 이 유형의 정보 표시는 기기의 배터리 잔량이나 목표 달성까지 남은 걸음 수를 보여주는 데 유용합니다.

1fe1943a5ad29076.png

CustomComplicationDataSourceService .kt를 열고 커서를 onComplicationRequest() 메서드의 when 문으로 이동한 후 이 코드를 TYPE_LONG_TEXT 사례 아래, 기본 사례 위에 추가합니다.

ComplicationType.RANGED_VALUE -> RangedValueComplicationData.Builder(
    value = number.toFloat(),
    min = 0f,
    max = ComplicationTapBroadcastReceiver.MAX_NUMBER.toFloat(),
    contentDescription = PlainComplicationText
        .Builder(text = "Ranged Value version of Number.").build()
)
    .setText(PlainComplicationText.Builder(text = numberText).build())
    .setTapAction(complicationPendingIntent)
    .build()

when 문은 다음과 같이 표시됩니다.

return when (request.complicationType) {

    ComplicationType.SHORT_TEXT -> ShortTextComplicationData.Builder(
        text = PlainComplicationText.Builder(text = numberText).build(),
        contentDescription = PlainComplicationText
            .Builder(text = "Short Text version of Number.").build()
    )
        .setTapAction(complicationPendingIntent)
        .build()

    ComplicationType.LONG_TEXT -> LongTextComplicationData.Builder(
        text = PlainComplicationText.Builder(text = "Number: $numberText").build(),
        contentDescription = PlainComplicationText
            .Builder(text = "Long Text version of Number.").build()
    )
        .setTapAction(complicationPendingIntent)
        .build()

    ComplicationType.RANGED_VALUE -> RangedValueComplicationData.Builder(
        value = number.toFloat(),
        min = 0f,
        max = ComplicationTapBroadcastReceiver.MAX_NUMBER.toFloat(),
        contentDescription = PlainComplicationText
            .Builder(text = "Ranged Value version of Number.").build()
    )
        .setText(PlainComplicationText.Builder(text = numberText).build())
        .setTapAction(complicationPendingIntent)
        .build()

    else -> {
        if (Log.isLoggable(TAG, Log.WARN)) {
            Log.w(TAG, "Unexpected complication type ${request.complicationType}")
        }
        null
    }
}

앞서 언급했듯이 같은 데이터를 새 형식으로 재구성할 뿐입니다. 어떻게 표시되는지 살펴보겠습니다.

진행 상황을 확인하고 디버그하는 방법

서비스를 설치하고 다른 위치를 선택합니다.

461f8a704fbc6496.png

이제 다음과 같이 표시됩니다.

ffa6ea8f2ed3eb2a.png

숫자 주위에 3/20과 동등한 값을 강조표시하는 방사형 원을 확인할 수 있습니다.

요약

이 단계에서 알아본 내용은 다음과 같습니다.

  • 다양한 정보 표시 데이터 유형 변경 및 지원

다음 단계

모든 데이터 유형 변형을 사용 설정하여 Codelab을 마무리합니다.

6. 세 가지 데이터 유형 모두 노출

코드 단계 6

이제 정보 표시 데이터 소스가 데이터의 세 가지 변형(RANGED_VALUE, SHORT_TEXT, LONG_TEXT)을 지원합니다.

이 마지막 단계에서는 시스템에 세 가지 변형을 모두 지원한다고 알립니다.

지원되는 여러 데이터 유형 지정

AndroidManifest.xml 파일을 다시 열고 서비스 CustomComplicationDataSourceService를 확인합니다.

meta-data 요소 SUPPORTED_TYPESRANGED_VALUE,SHORT_TEXT,LONG_TEXT로 변경합니다. 이제 변경사항이 다음과 같이 표시됩니다.

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

진행 상황 확인

서비스를 설치합니다.

b3a7c0c8063c2f60.png

여기서는 시계 화면에서 짧은 유형과 긴 유형보다 범위 지정 데이터 유형을 선호하지만 정보 표시에서 짧은 텍스트 유형만 지원하더라도 데이터가 여전히 표시됩니다. 시계 화면에서 세 가지 데이터 유형을 모두 지원하기 때문입니다. 시계 화면 자체는 정보 표시에서 지원하는 데이터 유형과 이러한 유형의 환경설정 순서를 지정합니다.

요약

이 단계에서 알아본 내용은 다음과 같습니다.

  • 여러 정보 표시 데이터 유형 지원

7. 모두 마쳤습니다! 다음 단계는 무엇일까요?

정보 표시에서 지원할 수 있는 데이터 유형은 작은 이미지, 큰 이미지, 아이콘 등 매우 많습니다. 이러한 유형 중 일부를 직접 구현하여 이 Codelab을 확장해 보세요.

시계 화면의 정보 표시 개발과 정보 표시 데이터 소스 생성에 관한 자세한 내용은 시계 화면 정보 표시를 참고하세요.

Wear OS 시계 화면 개발에 관한 자세한 내용은 https://developer.android.com/training/wearables/watch-faces/index.html에서 확인할 수 있습니다.