Best Practices für die Verwaltung von FCM-Registrierungstokens

Wenn Sie FCM APIs verwenden, um Sendeanfragen programmatisch zu erstellen, kann es sein, dass Sie im Laufe der Zeit Ressourcen verschwenden, indem Sie Nachrichten an inaktive Geräte mit veralteten Registrierungstokens senden. Diese Situation kann sich auf die in der Firebase Console erfassten Daten zur Nachrichtenübermittlung oder auf Daten auswirken, die nach BigQuery exportiert wurden. Dies kann zu einem drastischen (aber nicht tatsächlich gültigen) Rückgang der Übermittlungsraten führen. In diesem Leitfaden werden einige Maßnahmen beschrieben, mit denen Sie ein effizientes Targeting von Nachrichten und gültige Berichte zur Zustellung erzielen 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 in den Speicher gelegt 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 das 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 zu aktualisieren, wenn sich etwas ändert, z. B. in 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. 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 gespeichert, indem sendTokenToServer aufgerufen wird:

    /**
     * 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 auf dem neuesten Stand 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. Sie müssen also selbst die Kriterien festlegen, die für Sie am besten 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. Wenn Sie beispielsweise ungültige Tokens aus Cloud Firestore löschen möchten, können Sie 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 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 ist Folgendes zu tun:

  • 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 vom Zeitmuster sollten Sie 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önnen beispielsweise Cloud Functions for Firebase implementieren, um täglich zu prüfen, ob sich der Zeitstempel innerhalb eines definierten Zeitfensters für abgelaufene Tokens wie const EXPIRATION_TIME = 1000 * 60 * 60 * 24 * 30; befindet, und dann abgelaufene 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 sind. Dazu sind zwei Schritte erforderlich:

  1. Ihre App sollte sich einmal pro Monat und jedes Mal neu für Themen registrieren, wenn sich das Registrierungstoken ändert. Dies ist eine selbstheilende Lösung, bei der die Abos automatisch wieder angezeigt werden, wenn eine App wieder aktiv wird.
  2. Wenn eine App-Instanz einen Monat lang inaktiv ist (oder so lange, wie es in Ihrem eigenen Zeitfenster für die Zeitüberschreitung festgelegt ist), 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 Nachrichtenübermittlung zu erhalten, sollten Sie Nachrichten nur an aktiv verwendete App-Instanzen 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.