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 Zeitachse.

Diagramm der Kachelzeitachse

Kacheln mit einem einzelnen Eintrag

Häufig kann eine Kachel mit einer einzelnen TimelineEntry beschrieben werden. Das Layout ist unveränderlich und nur die Informationen innerhalb des Layouts ändern sich. Beispielsweise zeigt eine Kachel, die deinen Fitnessfortschritt an diesem Tag zeigt, immer das gleiche Fortschrittslayout an, auch wenn du dieses Layout anpassen kannst, um andere Werte anzuzeigen. In diesen Fällen wissen Sie im Voraus nicht, wann sich der Inhalt ändern wird.

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

Ein TimelineEntry kann optional einen Gültigkeitszeitraum definieren, sodass das Layout einer Kachel zu einem bekannten Zeitpunkt geändert werden kann, ohne dass die App eine neue Kachel übertragen muss.

Das kanonische Beispiel ist eine Agendakachel, deren Zeitachse eine Liste anstehender Ereignisse enthält. Für jedes bevorstehende Ereignis gibt es einen Gültigkeitszeitraum, der angibt, wann es angezeigt werden soll.

Die Tile API ermöglicht sich überschneidende Gültigkeitszeiträume. Dabei wird der Bildschirm mit der kürzesten verbleibenden Zeit angezeigt. 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 enthalten, 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 in einer Kachel angezeigten Informationen laufen möglicherweise nach einiger Zeit ab. Eine Wetterkachel, die den ganzen Tag über dieselbe Temperatur anzeigt, ist beispielsweise nicht genau.

Wenn Sie ablaufende Daten verarbeiten möchten, legen Sie beim Erstellen einer Kachel ein Aktualitätsintervall fest, das angibt, wie lange die Kachel gültig ist. Im Beispiel der Wetterkachel können Sie deren 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, ruft das System kurz nach Ablauf des Intervalls onTileRequest() auf. Wenn Sie kein Aktualitätsintervall festlegen, wird onTileRequest() nicht aufgerufen.

Eine Tile kann auch aufgrund eines externen Ereignisses ablaufen. Ein Nutzer kann beispielsweise eine Besprechung aus seinem Kalender entfernen. Wenn die Kachel nicht aktualisiert wurde, wird die gelöschte Besprechung weiterhin angezeigt. Fordern Sie in diesem Fall von jeder Stelle im Anwendungscode 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

Orientieren Sie sich an den folgenden Best Practices, um festzulegen, wie Sie Ihre Kachel-Updates konfigurieren:

  • Wenn die Aktualisierung vorhersehbar ist, z. B. beim nächsten Termin im Kalender des Nutzers, verwenden Sie eine Zeitachse.
  • Verwenden Sie beim Abrufen von Plattformdaten die Datenbindung, damit das System die Daten automatisch aktualisiert.
  • Wenn das Update innerhalb eines kurzen Zeitraums auf dem Gerät berechnet werden kann (z. B. Aktualisierung der Position eines Bilds auf einer Sonnenaufgangskachel), verwenden Sie 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. das Abfragen von Wetterdaten, verwenden Sie WorkManager und übertragen Sie Aktualisierungen auf Ihre Kachel.

  • Wenn die Aktualisierung als Reaktion auf ein externes Ereignis erfolgt, z. B. wenn die Lichter eingeschaltet werden, eine E-Mail empfangen oder eine Notiz aktualisiert wird, senden Sie eine Firebase Cloud Messaging (FCM)-Nachricht, um Ihre Anwendung wieder zu aktivieren, und übertragen Sie dann die Aktualisierungen an die Kachel.

  • Wenn das Synchronisieren der Kacheldaten kostspielig 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 ein Update von einer Remote-Datenquelle erhalten, zeigen Sie den aktualisierten Wert aus der Datensynchronisierung an. Andernfalls zeigen Sie einen im Cache gespeicherten lokalen Wert an.