Best Practices für die Verwaltung von FCM-Registrierungstokens

Wenn Sie FCM-APIs verwenden, um Sendeanfragen programmatisch zu erstellen, werden Sie feststellen, dass Sie mit der Zeit Ressourcen verschwenden, indem Sie Nachrichten mit veralteten Registrierungstokens an inaktive Geräte senden. Diese Situation kann sich auf die in der Firebase Console gemeldeten Nachrichtenzustellungsdaten oder die nach BigQuery exportierten Daten auswirken und einen drastischen (aber nicht gültigen) Rückgang der Zustellungsraten zeigen. In diesem Leitfaden werden einige Maßnahmen beschrieben, mit denen Sie ein effizientes Targeting von Nachrichten und gültige Berichte zur Zustellung erreichen können.

Veraltete und abgelaufene Registrierungstokens

Abgelaufene Registrierungstokens sind Tokens, die mit inaktiven Geräten verknüpft sind, die seit über einem Monat nicht mit FCM verbunden waren. Mit der Zeit wird es immer unwahrscheinlicher, dass das Gerät wieder eine Verbindung zu FCM herstellen kann. Nachrichtenübermittlungen und Themenfanouts für diese abgelaufenen Tokens werden wahrscheinlich nie zugestellt.

Es gibt mehrere Gründe, warum ein Token ungültig werden kann. Das Gerät, mit dem das Token verknüpft ist, kann beispielsweise verloren gehen, zerstört werden oder im Lager verstaut und vergessen werden.

Wenn bei abgelaufenen Tokens 270 Tage Inaktivität erreicht werden, werden sie von FCM als abgelaufene Tokens betrachtet. Sobald ein Token abgelaufen ist, kennzeichnet FCM es als ungültig und lehnt Sendungen an das Token ab. In seltenen Fällen, in denen das Gerät wieder eine Verbindung herstellt und die App geöffnet wird, stellt FCM jedoch ein neues Token für die App-Instanz aus.

Grundlegende Best Practices

Bei jeder App, in der FCM APIs verwendet werden, um Anfragen programmatisch zu senden, sollten Sie einige grundlegende Praktiken beachten. Die wichtigsten Best Practices sind:

  • Registrierungstokens von FCM abrufen und auf deinem Server speichern Eine wichtige Aufgabe des Servers besteht darin, das Token jedes Clients im Blick zu behalten und eine aktuelle Liste der aktiven Tokens zu führen. Wir empfehlen dringend, einen Token-Zeitstempel in Ihrem Code und auf Ihren Servern zu implementieren und diesen Zeitstempel in regelmäßigen Abständen zu aktualisieren.
  • Achte darauf, dass die Tokens immer aktuell sind, und entferne veraltete Tokens. Neben dem Entfernen von Tokens, die von FCM nicht mehr als gültig betrachtet werden, sollten Sie auch andere Anzeichen dafür beobachten, dass Tokens veraltet sind, und sie proaktiv entfernen. In diesem Leitfaden werden einige Optionen beschrieben, wie Sie dies erreichen können.

Registrierungstokens abrufen und speichern

Beim ersten Starten Ihrer App generiert das FCM SDK ein Registrierungstoken für die Client-App-Instanz. Dieses Token muss in Anfragen für gezielte Übermittlungen aus der API enthalten sein oder zu Themenabos für das Targeting auf Themen hinzugefügt werden.

Wir empfehlen dringend, dass Ihre App dieses Token beim ersten Start abrufen und zusammen mit einem Zeitstempel auf Ihrem App-Server speichern soll. Dieser Zeitstempel muss von Ihrem Code und Ihren Servern implementiert werden, da er nicht von den FCM SDKs bereitgestellt wird.

Außerdem ist es wichtig, das Token auf dem Server zu speichern und den Zeitstempel bei jeder Änderung zu aktualisieren, z. B. in den folgenden Fällen:

  • Die App wird auf einem neuen Gerät wiederhergestellt
  • Der Nutzer deinstalliert oder installiert die App neu
  • Der Nutzer löscht App-Daten
  • Die App wird wieder aktiv, nachdem das vorhandene Token von FCM abgelaufen ist.

Beispiel: Tokens und Zeitstempel in Cloud Firestore speichern

Sie können beispielsweise Cloud Firestore verwenden, um Tokens in einer Sammlung namens fcmTokens zu speichern. Jede Dokument-ID in der Sammlung entspricht einer Nutzer-ID und im Dokument werden das aktuelle Registrierungstoken und der Zeitstempel der letzten Aktualisierung gespeichert. Verwenden Sie die Funktion set, wie in diesem Kotlin-Beispiel gezeigt:

    /**
     * Persist token to third-party servers.
     *
     * Modify this method to associate the user's FCM registration token with any server-side account
     * maintained by your application.
     *
     * @param token The new token.
     */
    private fun sendTokenToServer(token: String?) {
        // If you're running your own server, call API to send token and today's date for the user

        // Example shown below with Firestore
        // Add token and timestamp to Firestore for this user
        val deviceToken = hashMapOf(
            "token" to token,
            "timestamp" to FieldValue.serverTimestamp(),
        )
        // Get user ID from Firebase Auth or your own server
        Firebase.firestore.collection("fcmTokens").document("myuserid")
            .set(deviceToken)
    }

Wenn ein Token abgerufen wird, wird es in Cloud Firestore durch Aufrufen von sendTokenToServer gespeichert:

    /**
     * Called if the FCM registration token is updated. This may occur if the security of
     * the previous token had been compromised. Note that this is called when the
     * FCM registration token is initially generated so this is where you would retrieve the token.
     */
    override fun onNewToken(token: String) {
        Log.d(TAG, "Refreshed token: $token")

        // If you want to send messages to this application instance or
        // manage this apps subscriptions on the server side, send the
        // FCM registration token to your app server.
        sendTokenToServer(token)
    }
        var token = Firebase.messaging.token.await()

        // Check whether the retrieved token matches the one on your server for this user's device
        val preferences = this.getPreferences(Context.MODE_PRIVATE)
        val tokenStored = preferences.getString("deviceToken", "")
        lifecycleScope.launch {
            if (tokenStored == "" || tokenStored != token)
            {
                // If you have your own server, call API to send the above token and Date() for this user's device

                // Example shown below with Firestore
                // Add token and timestamp to Firestore for this user
                val deviceToken = hashMapOf(
                    "token" to token,
                    "timestamp" to FieldValue.serverTimestamp(),
                )

                // Get user ID from Firebase Auth or your own server
                Firebase.firestore.collection("fcmTokens").document("myuserid")
                    .set(deviceToken).await()
            }
        }

Token aktuell halten und veraltete Tokens entfernen

Es ist nicht immer einfach zu bestimmen, ob ein Token gültig ist oder nicht. Um alle Fälle abzudecken, sollten Sie einen Grenzwert festlegen, ab dem Tokens als veraltet betrachtet werden. Standardmäßig betrachtet FCM ein Token als veraltet, wenn seine App-Instanz seit einem Monat nicht mehr verbunden war. Bei einem Token, das älter als ein Monat ist, handelt es sich wahrscheinlich um ein inaktives Gerät. Bei einem aktiven Gerät würde das Token andernfalls aktualisiert.

Je nach Anwendungsfall kann ein Monat zu kurz oder zu lang sein. Daher müssen Sie selbst entscheiden, welche Kriterien für Sie geeignet sind.

Ungültige Tokenantworten vom FCM-Backend erkennen

Achten Sie darauf, ungültige Tokenantworten von FCM zu erkennen, und löschen Sie alle Registrierungstokens, die bekanntlich ungültig oder abgelaufen sind. Bei der HTTP v1 API können diese Fehlermeldungen darauf hinweisen, dass Ihre Sendeanfrage auf ungültige oder abgelaufene Tokens ausgerichtet war:

  • UNREGISTERED (HTTP 404)
  • INVALID_ARGUMENT (HTTP 400)

Wenn Sie sicher sind, dass die Nachrichtennutzlast gültig ist, und Sie eine dieser Antworten für ein Targeting-Token erhalten, können Sie den Eintrag für dieses Token löschen, da es nie wieder gültig sein wird. Zum Löschen ungültiger Tokens aus Cloud Firestore können Sie beispielsweise eine Funktion wie die folgende bereitstellen und ausführen:

    // Registration token comes from the client FCM SDKs
    const registrationToken = 'YOUR_REGISTRATION_TOKEN';

    const message = {
    data: {
        // Information you want to send inside of notification
    },
    token: registrationToken
    };

    // Send message to device with provided registration token
    getMessaging().send(message)
    .then((response) => {
        // Response is a message ID string.
    })
    .catch((error) => {
        // Delete token for user if error code is UNREGISTERED or INVALID_ARGUMENT.
        if (errorCode == "messaging/registration-token-not-registered") {
            // If you're running your own server, call API to delete the
            token for the user

            // Example shown below with Firestore
            // Get user ID from Firebase Auth or your own server
            Firebase.firestore.collection("fcmTokens").document(user.uid).delete()
        }
    });

FCM gibt nur dann eine ungültige Tokenantwort zurück, wenn ein Token nach 270 Tagen abgelaufen ist oder ein Client explizit abgemeldet wurde. Wenn Sie die Gültigkeit Ihrer Registrierungstokens gemäß Ihren eigenen Definitionen genauer erfassen möchten, können Sie veraltete Registrierungstokens proaktiv entfernen.

Aktualisieren Sie Tokens regelmäßig.

Wir empfehlen, alle Registrierungstokens regelmäßig auf deinem Server abzurufen und zu aktualisieren. Dazu sind folgende Schritte erforderlich:

  • Fügen Sie Ihrer Clientanwendung App-Logik hinzu, um das aktuelle Token mit dem entsprechenden API-Aufruf abzurufen (z. B. token(completion): für Apple-Plattformen oder getToken() für Android) und senden Sie es dann zum Speichern (mit einem Zeitstempel) an Ihren App-Server. Dies kann ein monatlicher Job sein, der so konfiguriert ist, dass alle Kunden oder Tokens abgedeckt werden.
  • Fügen Sie Serverlogik hinzu, um den Zeitstempel des Tokens in regelmäßigen Abständen zu aktualisieren, unabhängig davon, ob sich das Token geändert hat.

Ein Beispiel für die Android-Logik zum Aktualisieren von Tokens mit WorkManager finden Sie im Firebase-Blog unter Cloud Messaging-Tokens verwalten.

Unabhängig von Ihrem Timing-Muster sollten Sie die Tokens regelmäßig aktualisieren. Eine Aktualisierungshäufigkeit von einmal im Monat bietet ein gutes Gleichgewicht zwischen Akkubelastung und Erkennung inaktiver Registrierungstokens. Durch diese Aktualisierung wird auch sichergestellt, dass die Registrierung aller Geräte, die inaktiv werden, aktualisiert wird, sobald sie wieder aktiv werden. Eine häufigere Aktualisierung bringt keine Vorteile.

Veraltete Registrierungstokens entfernen

Bevor Sie Nachrichten an ein Gerät senden, prüfen Sie, ob der Zeitstempel des Registrierungstokens des Geräts innerhalb des Zeitfensters für die Gültigkeit liegt. Sie könnten beispielsweise Cloud Functions for Firebase implementieren, um eine tägliche Prüfung durchzuführen, um dafür zu sorgen, dass sich der Zeitstempel innerhalb eines definierten Veralterungsfensters wie const EXPIRATION_TIME = 1000 * 60 * 60 * 24 * 30; befindet, und dann veraltete Tokens entfernen:

exports.pruneTokens = functions.pubsub.schedule('every 24 hours').onRun(async (context) => {
  // Get all documents where the timestamp exceeds is not within the past month
  const staleTokensResult = await admin.firestore().collection('fcmTokens')
      .where("timestamp", "<", Date.now() - EXPIRATION_TIME)
      .get();
  // Delete devices with stale tokens
  staleTokensResult.forEach(function(doc) { doc.ref.delete(); });
});

Abgelaufene Tokens von Themen abmelden

Wenn Sie Themen verwenden, sollten Sie auch veraltete Tokens von den Themen abmelden, für die sie abonniert wurden. Dazu sind zwei Schritte erforderlich:

  1. Ihre Anwendung sollte Themen einmal pro Monat und immer dann neu abonnieren, wenn sich das Registrierungstoken ändert. Dies bildet eine selbstheilende Lösung, bei der die Abos automatisch wieder angezeigt werden, wenn eine App wieder aktiv wird.
  2. Wenn eine Anwendungsinstanz einen Monat lang inaktiv ist (oder Ihr eigenes Veralterungsfenster), sollten Sie sie mit dem Firebase Admin SDK von Themen abmelden, um die Zuordnung des Tokens zum Thema aus dem FCM-Back-End zu löschen.

Der Vorteil dieser beiden Schritte besteht darin, dass die Fan-outs schneller erfolgen, da es weniger ablaufende Tokens gibt, auf die sie verteilt werden können. Außerdem werden Ihre abgelaufenen App-Instanzen automatisch wieder abonniert, sobald sie wieder aktiv sind.

Erfolg der Auslieferung messen

Um ein möglichst genaues Bild der Nachrichtenzustellung zu erhalten, ist es am besten, Nachrichten nur an aktiv verwendete Anwendungsinstanzen zu senden. Das ist besonders wichtig, wenn Sie regelmäßig Nachrichten an Themen mit einer großen Anzahl von Abonnenten senden. Wenn ein Teil dieser Abonnenten inaktiv ist, kann sich das im Laufe der Zeit erheblich auf Ihre Zustellungsstatistiken auswirken.

Bevor Sie Nachrichten auf ein Token ausrichten, sollten Sie Folgendes berücksichtigen:

  • Geben Google Analytics, in BigQuery erfasste Daten oder andere Tracking-Signale an, dass das Token aktiv ist?
  • Sind vorherige Übermittlungsversuche über einen bestimmten Zeitraum hinweg immer fehlgeschlagen?
  • Wurde das Registrierungstoken in den letzten 30 Tagen auf Ihren Servern aktualisiert?
  • Gibt die FCM Data API für Android-Geräte einen hohen Prozentsatz von Übermittlungsfehlern aufgrund von droppedDeviceInactive an?

Weitere Informationen zur Zustellung finden Sie unter E-Mail-Zustellung.