Regelmäßige Updates in Kacheln anzeigen

Erstellen Sie Kacheln mit Inhalten, die sich im Laufe der Zeit ändern.

Mit Zeitplänen arbeiten

Eine Zeitachse besteht aus einer oder mehreren TimelineEntry-Instanzen, von denen jede ein Layout enthält, das während eines bestimmten Zeitintervalls angezeigt wird. Alle Kacheln benötigen eine Zeitleiste.

Diagramm der Kachelzeitachse

Kacheln mit einem einzelnen Eintrag

Häufig kann eine Kachel mit einer einzelnen TimelineEntry beschrieben werden. Das Layout ist fixiert und nur die darin enthaltenen Informationen ändern sich. Beispielsweise zeigt eine Kachel, die Ihren Fitnessfortschritt des Tages zeigt, immer dasselbe Fortschrittslayout an, auch wenn Sie dieses Layout anpassen können, um verschiedene Werte anzuzeigen. In diesen Fällen wissen Sie im Voraus nicht, wann sich der Inhalt ändern könnte.

Hier ein Beispiel für eine Kachel mit einem einzelnen 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);
}

Zeitgebundene Zeitachseneinträge

Eine TimelineEntry kann optional einen Gültigkeitszeitraum definieren, sodass eine Kachel ihr Layout zu einem bekannten Zeitpunkt ändern kann, ohne dass die Anwendung eine neue Kachel senden muss.

Das kanonische Beispiel ist eine Agendakachel, deren Zeitachse eine Liste der bevorstehenden Ereignisse enthält. Jedes bevorstehende Ereignis enthält einen Gültigkeitszeitraum, aus dem hervorgeht, wann es angezeigt werden soll.

Die Tiles API ermöglicht überlappende Gültigkeitszeiträume, wobei der Bildschirm mit der kürzesten verbleibenden Zeit angezeigt wird. Es wird jeweils nur ein Ereignis angezeigt.

Entwickler können einen Standard-Fallback-Eintrag angeben. Die Agendakachel könnte beispielsweise eine Kachel mit einem unendlichen Gültigkeitszeitraum haben, der verwendet wird, wenn kein anderer Zeitachseneintrag gültig ist, wie im folgenden Codebeispiel gezeigt:

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

Kachel aktualisieren

Die auf einer Kachel angezeigten Informationen können nach einiger Zeit ablaufen. So ist beispielsweise eine Wetterkachel, auf der über den Tag verteilt die gleiche Temperatur angezeigt wird, nicht genau.

Um mit ablaufenden Daten umzugehen, legen Sie beim Erstellen einer Kachel ein Aktualitätsintervall fest, das angibt, wie lange die Kachel gültig ist. Bei der Wetterkachel könnten Sie den Inhalt stündlich aktualisieren, wie im folgenden Codebeispiel gezeigt:

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

Wenn Sie ein Aktualitätsintervall festlegen, wird kurz nach Ablauf des Intervalls onTileRequest() aufgerufen. Wenn Sie kein Aktualitätsintervall festlegen, ruft das System onTileRequest() nicht auf.

Eine Kachel kann auch aufgrund eines externen Ereignisses ablaufen. Beispielsweise kann ein Nutzer eine Besprechung aus seinem Kalender entfernen. Wenn die Kachel nicht aktualisiert wurde, wird die gelöschte Besprechung weiterhin in der Kachel angezeigt. Fordern Sie in diesem Fall von jeder Stelle Ihres Anwendungscodes aus eine Aktualisierung an, wie im folgenden Codebeispiel gezeigt:

Kotlin

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

Java

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

Aktualisierungsworkflow auswählen

Halten Sie sich an die folgenden Best Practices, um festzulegen, wie Sie Ihre Kachelaktualisierungen konfigurieren:

  • Wenn die Aktualisierung vorhersehbar ist, z. B. wenn der nächste Termin im Kalender des Nutzers stattfindet, verwenden Sie eine Zeitachse.
  • Verwenden Sie beim Abrufen von Plattformdaten die Datenbindung, damit das System die Daten automatisch aktualisiert.
  • Wenn die Aktualisierung in kurzer Zeit auf dem Gerät berechnet werden kann – z. B. wenn die Position eines Bildes auf einer Sonnenaufgangskachel aktualisiert wird –, verwende onTileRequest().

    Dies ist besonders nützlich, wenn Sie alle Bilder im Voraus generieren müssen. Wenn Sie später ein neues Bild generieren müssen, rufen Sie setFreshnessIntervalMillis() auf.

  • Wenn Sie wiederholt intensivere Hintergrundarbeiten ausführen, z. B. Wetterdaten abfragen, verwenden Sie WorkManager und übertragen Sie Aktualisierungen auf Ihre Kachel.

  • Wenn das Update als Reaktion auf ein externes Ereignis erfolgt, z. B. wenn das Licht eingeschaltet wird, eine E-Mail empfangen oder eine Notiz aktualisiert wird, senden Sie eine Firebase Cloud Messaging-Nachricht (FCM), um Ihre App wieder zu aktivieren. Übertragen Sie dann die Updates an die Kachel.

  • Wenn die Synchronisierung der Kacheldaten teuer sein könnte, gehen Sie so vor:

    1. Datensynchronisierung planen
    2. Starte einen Timer für 1 bis 2 Sekunden.
    3. Wenn Sie vor Ablauf der Zeit eine Aktualisierung von einer Remote-Datenquelle erhalten, wird der aktualisierte Wert aus der Datensynchronisierung angezeigt. Andernfalls wird ein im Cache gespeicherter lokaler Wert angezeigt.