카드에서 주기적인 업데이트 표시

시간이 지남에 따라 변경되는 콘텐츠를 포함하는 카드를 만듭니다.

타임라인 사용

타임라인은 하나 이상의 TimelineEntry 인스턴스로 구성됩니다. 각 인스턴스는 특정 시간 간격 동안 표시되는 레이아웃을 포함합니다. 모든 카드에는 타임라인이 필요합니다.

카드 타임라인 다이어그램

단일 항목 카드

카드는 하나의 TimelineEntry로 설명할 수 있는 경우가 많습니다. 레이아웃은 고정되어 있고 레이아웃 내부의 정보만 변경됩니다. 예를 들어, 하루의 피트니스 진행 상황을 보여주는 카드는 다른 값을 표시하도록 레이아웃을 ���정해도 항상 동일한 진행 상황 레이아웃을 표시합니다. 이때 콘텐츠가 언제 변경될지 미리 알 수 없습니다.

단일 TimelineEntry를 갖는 카드의 예를 참고하세요.

Kotlin

override fun onTileRequest(
    requestParams: TileRequest
): ListenableFuture<Tile> {
    val tile = Tile.Builder()
        .setResourcesVersion(RESOURCES_VERSION)

        // We add a single timeline entry when our layout is fixed, and
        // we don't know in advance when its contents might change.
        .setTileTimeline(
            Timeline.fromLayoutElement(...)
        ).build()
    return Futures.immediateFuture(tile)
}

Java

@Override
protected ListenableFuture<Tile> onTileRequest(
       @NonNull TileRequest requestParams
) {
   Tile tile = new Tile.Builder()
       .setResourcesVersion(RESOURCES_VERSION)
       
       // We add a single timeline entry when our layout is fixed, and
       // we don't know in advance when its contents might change.
       .setTileTimeline(
            Timeline.fromLayoutElement(...)
       ).build();
   return Futures.immediateFuture(tile);
}

기한이 있는 타임라인 항목

TimelineEntry는 선택적으로 유효 기간을 정의할 수 있으며 이에 따라 앱이 새 카드를 푸시하지 않아도 카드가 알려진 시간에 레이아웃을 변경할 수 있습니다.

표준 예로 타임라인에 향후 이벤트 목록이 포함된 일정 카드를 들 수 있습니다. 각 향후 이벤트에는 이벤트가 표시되는 시점을 나타내는 유효 기간이 포함됩니다.

Tiles API를 사용하면 유효 기간을 중복하여 지정할 수 있습니다. 유효 기간이 중복 지정된 경우 남은 시간이 가장 짧은 화면이 표시됩니다. 한 번에 하나의 이벤트만 표시됩니다.

개발자가 대체 항목 기본값을 제공할 수 있습니다. 예를 들어, 일정 카드에 유효 기간이 무한한 다른 카드를 갖는 경우 이 카드는 다음 코드 샘플과 같이 다른 유효한 타임라인 항목이 없을 때 사용됩니다.

Kotlin

public override fun onTileRequest(
    requestParams: TileRequest
): ListenableFuture<Tile> {
    val timeline = Timeline.Builder()

    // Add fallback "no meetings" entry
    // Use the version of TimelineEntry that's in androidx.wear.protolayout.
    timeline.addTimelineEntry(TimelineEntry.Builder()
        .setLayout(getNoMeetingsLayout())
        .build()
    )

    // Retrieve a list of scheduled meetings
    val meetings = MeetingsRepo.getMeetings()
    // Add a timeline entry for each meeting
    meetings.forEach { meeting ->
        timeline.addTimelineEntry(TimelineEntry.Builder()
            .setLayout(getMeetingLayout(meeting))
            .setValidity(
                // The tile should disappear when the meeting begins
                // Use the version of TimeInterval that's in
                // androidx.wear.protolayout.
                TimeInterval.Builder()
                    .setEndMillis(meeting.dateTimeMillis).build()
            ).build()
        )
    }

    val tile = Tile.Builder()
        .setResourcesVersion(RESOURCES_VERSION)
        .setTileTimeline(timeline.build())
        .build()
    return Futures.immediateFuture(tile)
}

Java

@Override
protected ListenableFuture<Tile> onTileRequest(
       @NonNull RequestBuilders.TileRequest requestParams
) {
   Timeline.Builder timeline = new Timeline.Builder();
   // Add fallback "no meetings" entry
   // Use the version of TimelineEntry that's in androidx.wear.protolayout.
   timeline.addTimelineEntry(new TimelineEntry.Builder().setLayout(getNoMeetingsLayout()).build());
   // Retrieve a list of scheduled meetings
   List<Meeting> meetings = MeetingsRepo.getMeetings();
   // Add a timeline entry for each meeting
   for(Meeting meeting : meetings) {
        timeline.addTimelineEntry(new TimelineEntry.Builder()
            .setLayout(getMeetingLayout(meeting))
            .setValidity(
                // The tile should disappear when the meeting begins
                // Use the version of TimeInterval that's in
                // androidx.wear.protolayout.
                new TimeInterval.builder()
                    .setEndMillis(meeting.getDateTimeMillis()).build()
            ).build()
        );
    }

    Tile tile = new Tile.Builder()
        .setResourcesVersion(RESOURCES_VERSION)
        .setTileTimeline(timeline.build())
        .build();
    return Futures.immediateFuture(tile);
}

카드 새로고침

카드에 표시된 정보는 일정 시간이 지나면 만료될 수 있습니다. 예를 들어, 하루 종일 동일한 온도를 표시하는 날씨 카드는 정확하지 않습니다.

만료되는 데이터를 처리하려면 카드 생성 시점에 카드의 유효 기간을 지정하는 새로고침 간격을 설정합니다. 날씨 카드의 경우 다음 코드 샘플과 같이 1시간에 한 번 콘텐츠를 업데이트할 수 있습니다.

Kotlin

override fun onTileRequest(requestParams: RequestBuilders.TileRequest) =
    Futures.immediateFuture(Tile.Builder()
        .setResourcesVersion(RESOURCES_VERSION)
        .setFreshnessIntervalMillis(60 * 60 * 1000) // 60 minutes
        .setTileTimeline(Timeline.fromLayoutElement(
            getWeatherLayout())
        ).build()
    )

Java

@Override
protected ListenableFuture<Tile> onTileRequest(
       @NonNull TileRequest requestParams
) {
    return Futures.immediateFuture(new Tile.Builder()
        .setResourcesVersion(RESOURCES_VERSION)
        .setFreshnessIntervalMillis(60 * 60 * 1000) // 60 minutes
        .setTimeline(Timeline.fromLayoutElement(
            getWeatherLayout())
        ).build());
}

새로고침 간격을 설정하면 시스템은 그 시간이 종료되면 곧 onTileRequest()를 호출합니다. 새로고침 간격을 설정하지 않으면 시스템이 onTileRequest()를 호출하지 않습니다.

카드가 외부 이벤트로 인해 만료되는 경우도 있습니다. 예를 들어, 사용자가 캘린더에서 회의를 삭제했는데 카드가 새로고침되지 않았다면 계속해서 삭제된 회의가 표시될 것입니다. 이 경우 다음 코드 샘플과 같이 애플리케이션 코드의 아무 데서나 새로고침을 요청하면 됩니다.

Kotlin

fun eventDeletedCallback() {
     TileService.getUpdater(context)
             .requestUpdate(MyTileService::class.java)
}

Java

public void eventDeletedCallback() {
   TileService.getUpdater(context)
           .requestUpdate(MyTileService.class);
}

업데이트 워크플로 선택

다음 권장사항에 따라 카드 업데이트를 구성할 방법을 정하세요.

  • 업데이트를 예측할 수 있는 경우(예: 사용자 캘린더의 다음 이벤트 업데이트인 경우) 타임라인을 사용합니다.
  • 플랫폼 데이터를 가져올 때는 시스템에서 자동으로 데이터를 업데이트하도록 데이터 결합을 사용합니다.
  • 짧은 시간 내에 기기에서 업데이트를 계산할 수 있는 경우(예: 일출 카드에서 이미지의 위치 업데이트) onTileRequest()를 사용합니다.

    이 기능은 모든 이미지를 미리 생성해야 하는 경우에 특히 유용합니다. 나중에 새 이미지를 생성해야 하는 경우에는 setFreshnessIntervalMillis()를 호출합니다.

  • 날씨 데이터 폴링과 같이 보다 집중적인 백그라운드 작업을 하는 경우에는 WorkManager를 사용하고 카드로 업데이트를 푸시합니다.

  • 업데이트가 외부 이벤트에 대한 응답인 경우(예: 조명이 켜짐, 이메일을 수신함, 메모가 업데이트됨) Firebase 클라우드 메시징(FCM) 메시지를 보내서 앱을 다시 활성화한 다음 카드로 업데이트를 푸시합니다.

  • 카드 데이터 동기화 프로세스에 비용이 많이 드는 경우에는 다음 단계를 따르세요.

    1. 데이터 동기화를 예약합니다.
    2. 1~2초 타이머를 시작합니다.
    3. 시간이 다 되기 전에 원격 데이터 소스에서 업데이트를 받은 경우 데이터 동기화로부터 업데이트된 값을 표시합니다. 그 밖의 경우에는 캐시된 로컬 값을 표시합니다.