Pokazuj okresowe aktualizacje w kafelkach

Twórz kafelki z treścią, która zmienia się z upływem czasu.

Praca z osiami czasu

Oś czasu składa się z co najmniej 1 instancji [TimelineEntry][1], z których każda zawiera układ wyświetlany w określonym przedziale czasu. Wszystkie kafelki wymagają osi czasu.

Diagram osi czasu kafelka

Kafelki z jednym wejściem

Często kafelek można opisać za pomocą jednego elementu TimelineEntry. Układ jest stały i zmieniają się tylko zawarte w nim informacje. Na przykład kafelek pokazujący Twoje postępy w aktywności fizycznej w danym dniu zawsze przedstawia ten sam układ postępów, ale możesz go dostosować tak, aby wyświetlały różne wartości. W takich przypadkach nie wiadomo z wyprzedzeniem, kiedy treść może ulec zmianie.

Zobacz ten przykład kafelka z pojedynczym elementem 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);
}

Wpisy na osi czasu ograniczone czasowo

TimelineEntry może opcjonalnie zdefiniować okres ważności, co pozwala kafelkowi zmieniać układ w znanym czasie bez konieczności przekazywania przez aplikację nowego kafelka.

Przykładem kanonicznym jest kafelek planu spotkania, którego oś czasu zawiera listę nadchodzących zdarzeń. Każde nadchodzące wydarzenie ma okres ważności, który określa, kiedy ma się wyświetlać.

Interfejs API kafelków umożliwia nakładanie się okresów ważności, przy czym wyświetlany jest ekran o najkrótszym czasie trwania. Wyświetlane jest tylko 1 zdarzenie naraz.

Deweloperzy mogą podać domyślny wpis kreacji zastępczej. Na przykład kafelek planu spotkania może mieć kafelek z nieskończonym okresem ważności, który jest używany, jeśli żadne inne wpisy na osi czasu nie są prawidłowe, tak jak w tym przykładowym kodzie:

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

Odświeżanie kafelka

Informacje widoczne na kafelku mogą po pewnym czasie wygasnąć. Na przykład kafelek pogody, który pokazuje tę samą temperaturę w ciągu dnia, nie jest dokładny.

Aby radzić sobie z wygasającymi danymi, ustaw przedział aktualności podczas tworzenia kafelka, który określa, jak długo kafelek jest ważny. W przykładzie kafelka pogody możesz aktualizować jego zawartość co godzinę, jak pokazano w tym przykładowym kodzie:

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

Gdy ustawisz interwał aktualności, system wywoła [onTileRequest()][2] krótko po jego zakończeniu. Jeśli nie ustawisz interwału aktualności, system nie wywoła onTileRequest().

Kafelek może też wygasnąć w wyniku wydarzenia zewnętrznego. Użytkownik mógł na przykład usunąć spotkanie ze swojego kalendarza, a jeśli kafelek nie został odświeżony, nadal będzie na nim widoczne to usunięte spotkanie. W takim przypadku poproś o odświeżenie z dowolnego miejsca w kodzie aplikacji, jak pokazano w tym przykładowym kodzie:

Kotlin

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

Java

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

Wybierz przepływ pracy związany z aktualizacją

Skorzystaj z tych sprawdzonych metod, aby określić sposób konfigurowania aktualizacji kafelków:

  • Jeśli aktualizacja jest przewidywalna – na przykład dotyczy następnego wydarzenia w kalendarzu użytkownika – użyj osi czasu.
  • Przy pobieraniu danych platformy użyj powiązania danych, aby system automatycznie aktualizował dane.
  • Jeśli aktualizację można przeprowadzić na urządzeniu w krótkim czasie, np. zmienić pozycję obrazu na kafelku wschodu słońca, użyj funkcji [onTileRequest()][2].

    Jest to szczególnie przydatne, gdy musisz wcześniej wygenerować wszystkie obrazy. Jeśli w przyszłości zechcesz wygenerować nowy obraz, wywołaj [setFreshnessIntervalMillis()][3].

  • Jeśli wykonujesz bardziej intensywne zadania w tle, np. przeprowadzasz sondowanie w celu uzyskania danych o pogodzie, użyj funkcji [WorkManager][4] i prześlij aktualizacje do kafelka.

  • Jeśli aktualizacja jest spowodowana zdarzeniem zewnętrznym – takim jak włączenie świateł, otrzymanie e-maila lub zaktualizowanie notatki – wyślij wiadomość [Komunikacja w chmurze Firebase (FCM)][5], aby ponownie aktywować aplikację, a następnie przekaż aktualizacje do kafelka.

  • Jeśli proces synchronizacji danych kafelków może być kosztowny, wykonaj te czynności:

    1. Zaplanuj synchronizację danych.
    2. Włącz minutnik na 1–2 sekundy.
    3. Jeśli otrzymasz aktualizację ze zdalnego źródła danych przed upływem czasu, pokaż zaktualizowaną wartość z synchronizacji danych. W przeciwnym razie pokazuj wartość lokalną z pamięci podręcznej.