Best Practices für die FCM-Registrierungstoken-Verwaltung

Wenn Sie FCM-APIs verwenden, um Sendeanforderungen programmgesteuert zu erstellen, stellen Sie möglicherweise fest, dass Sie mit der Zeit Ressourcen verschwenden, indem Sie Nachrichten an inaktive Geräte mit veralteten Registrierungstokens senden. Diese Situation kann sich auf die in der Firebase-Konsole gemeldeten Nachrichtenzustellungsdaten oder nach BigQuery exportierten Daten auswirken und sich in einem dramatischen (aber nicht wirklich gültigen) Rückgang der Zustellungsraten zeigen. In diesem Leitfaden werden einige Maßnahmen erläutert, die Sie ergreifen können, um eine effiziente Nachrichtenausrichtung und gültige Zustellungsberichte sicherzustellen.

Veraltete und abgelaufene Registrierungstoken

Veraltete Registrierungstoken sind Token, die mit inaktiven Geräten verknüpft sind, die seit mehr als einem Monat keine Verbindung zum FCM hatten. Mit der Zeit wird es immer unwahrscheinlicher, dass das Gerät jemals wieder eine Verbindung zum FCM herstellt. Es ist unwahrscheinlich, dass Nachrichtensendungen und Themen-Fanouts für diese veralteten Token jemals zugestellt werden.

Es gibt mehrere Gründe, warum ein Token veraltet sein kann. Beispielsweise kann das Gerät, mit dem der Token verknüpft ist, verloren gehen, zerstört oder eingelagert und vergessen werden.

Wenn veraltete Token 270 Tage Inaktivität erreichen, betrachtet FCM sie als abgelaufene Token . Sobald ein Token abläuft, markiert FCM es als ungültig und lehnt Sendungen an das Token ab. Für den seltenen Fall, dass das Gerät erneut eine Verbindung herstellt und die App geöffnet wird, stellt FCM jedoch ein neues Token für die App-Instanz aus.

Grundlegende Best Practices

Es gibt einige grundlegende Vorgehensweisen, die Sie in jeder App befolgen sollten, die FCM-APIs verwendet, um Sendeanforderungen programmgesteuert zu erstellen. Die wichtigsten Best Practices sind:

  • Rufen Sie Registrierungstokens von FCM ab und speichern Sie sie auf Ihrem Server. Eine wichtige Rolle des Servers besteht darin, den Überblick über die Token jedes Clients zu behalten und eine aktualisierte Liste der aktiven Token zu führen. Wir empfehlen dringend, in Ihrem Code und auf Ihren Servern einen Token-Zeitstempel zu implementieren und diesen Zeitstempel in regelmäßigen Abständen zu aktualisieren.
  • Behalten Sie die Aktualität der Token bei und entfernen Sie veraltete Token. Zusätzlich zum Entfernen von Token, die FCM nicht mehr als gültig erachtet, möchten Sie möglicherweise andere Anzeichen dafür überwachen, dass Token veraltet sind, und diese proaktiv entfernen. In diesem Leitfaden werden einige Möglichkeiten erläutert, wie Sie dies erreichen können.

Registrierungstoken abrufen und speichern

Beim ersten Start Ihrer App generiert das FCM SDK ein Registrierungstoken für die Client-App-Instanz. Dies ist das Token, das Sie in gezielte Sendeanfragen von der API einschließen oder zu Themenabonnements hinzufügen müssen, um Themen gezielt anzusprechen.

Wir empfehlen Ihrer App dringend, dieses Token beim ersten Start abzurufen und es zusammen mit einem Zeitstempel auf Ihrem App-Server zu speichern . Dieser Zeitstempel muss von Ihrem Code und Ihren Servern implementiert werden, da er Ihnen von FCM SDKs nicht bereitgestellt wird.

Außerdem ist es wichtig, das Token auf dem Server zu speichern und den Zeitstempel zu aktualisieren, wenn er sich ändert, z. B. wenn:

  • Die App wird auf einem neuen Gerät wiederhergestellt
  • Der Benutzer deinstalliert die App oder installiert sie erneut
  • Der Benutzer löscht App-Daten
  • Die App wird wieder aktiv, nachdem FCM sein vorhandenes Token abgelaufen ist

Beispiel: Token und Zeitstempel im Cloud Firestore speichern

Sie könnten beispielsweise Cloud Firestore verwenden, um Token in einer Sammlung namens fcmTokens zu speichern. Jede Dokument-ID in der Sammlung entspricht einer Benutzer-ID, und das Dokument speichert das aktuelle Registrierungstoken und seinen zuletzt aktualisierten Zeitstempel. Verwenden Sie die set Funktion 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)
    }

Immer wenn ein Token abgerufen wird, wird es durch den Aufruf von sendTokenToServer im Cloud Firestore 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()
            }
        }

Behalten Sie die Aktualität der Token bei und entfernen Sie veraltete Token

Es ist nicht immer einfach festzustellen, ob ein Token frisch oder veraltet ist. Um alle Fälle abzudecken, sollten Sie einen Schwellenwert festlegen, ab dem Sie Token als veraltet betrachten. Standardmäßig betrachtet FCM ein Token als veraltet, wenn seine App-Instanz einen Monat lang keine Verbindung hergestellt hat. Bei jedem Token, der älter als einen Monat ist, handelt es sich wahrscheinlich um ein inaktives Gerät. Ein aktives Gerät hätte andernfalls sein Token aktualisiert.

Abhängig von Ihrem Anwendungsfall kann ein Monat zu kurz oder zu lang sein. Es liegt also an Ihnen, die für Sie geeigneten Kriterien festzulegen.

Erkennen Sie ungültige Token-Antworten vom FCM-Backend

Stellen Sie sicher, dass Sie ungültige Token-Antworten von FCM erkennen und reagieren Sie, indem Sie alle Registrierungstokens, die bekanntermaßen ungültig oder abgelaufen sind, aus Ihrem System löschen. Bei der HTTP v1-API können diese Fehlermeldungen darauf hinweisen, dass Ihre Sendeanforderung auf ungültige oder abgelaufene Token abzielte:

  • 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 Ziel-Token erhalten, können Sie Ihren Datensatz dieses Tokens bedenkenlos löschen, da er nie wieder gültig sein wird. Um beispielsweise ungültige Token aus Cloud Firestore zu löschen, könnten 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 Token-Antwort zurück, wenn ein Token nach 270 Tagen abgelaufen ist oder wenn sich ein Client explizit abgemeldet hat. Wenn Sie die Veralterung gemäß Ihren eigenen Definitionen genauer verfolgen müssen, können Sie veraltete Registrierungstoken proaktiv entfernen .

Aktualisieren Sie die Token regelmäßig

Wir empfehlen Ihnen, regelmäßig alle Registrierungstokens auf Ihrem Server abzurufen und zu aktualisieren. Dies erfordert Folgendes:

  • Fügen Sie Ihrer Client-App App-Logik hinzu, um das aktuelle Token mithilfe des entsprechenden API-Aufrufs abzurufen (z. B. token(completion): für Apple-Plattformen oder getToken() für Android) und senden Sie dann das aktuelle Token zur Speicherung an Ihren App-Server (mit einem Zeitstempel). Dies könnte ein monatlicher Job sein, der so konfiguriert ist, dass er alle Clients oder Token abdeckt.
  • 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 oder nicht.

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

Unabhängig davon, welchem ​​Zeitmuster Sie folgen, stellen Sie sicher, dass Sie die Token regelmäßig aktualisieren. Eine Aktualisierungshäufigkeit von einmal pro Monat sorgt für ein gutes Gleichgewicht zwischen Batteriebelastung und Erkennung inaktiver Registrierungstokens. Durch diese Aktualisierung stellen Sie außerdem sicher, dass jedes Gerät, das inaktiv wird, seine Registrierung aktualisiert, wenn es wieder aktiv wird. Es hat keinen Vorteil, die Aktualisierung häufiger als wöchentlich durchzuführen.

Entfernen Sie veraltete Registrierungstoken

Stellen Sie vor dem Senden von Nachrichten an ein Gerät sicher, dass der Zeitstempel des Registrierungstokens des Geräts innerhalb Ihres Veraltungsfensterzeitraums liegt. Sie könnten beispielsweise Cloud Functions für Firebase implementieren, um eine tägliche Prüfung durchzuführen, um sicherzustellen, dass der Zeitstempel innerhalb eines definierten Veraltungsfensterzeitraums liegt, z. B. const EXPIRATION_TIME = 1000 * 60 * 60 * 24 * 30; und dann veraltete Token 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(); });
});

Abbestellen veralteter Token von Themen

Wenn Sie Themen verwenden, möchten Sie möglicherweise auch die Registrierung veralteter Token von den Themen aufheben, die sie abonniert haben. Dies umfasst zwei Schritte:

  1. Ihre App sollte Themen einmal im Monat und bei jeder Änderung des Registrierungstokens erneut abonnieren. Dadurch entsteht eine selbstheilende Lösung, bei der die Abonnements automatisch wieder angezeigt werden, wenn eine App wieder aktiv wird.
  2. Wenn eine App-Instanz einen Monat lang (oder Ihr eigenes Veraltungsfenster) inaktiv ist, sollten Sie sie mithilfe des Firebase Admin SDK von Themen abmelden, um die Token-zu-Themen-Zuordnung aus dem FCM-Backend zu löschen.

Der Vorteil dieser beiden Schritte besteht darin, dass Ihr Fanout schneller erfolgt, da weniger veraltete Token zum Fanout vorhanden sind und Ihre veralteten App-Instanzen automatisch erneut abonniert werden, sobald sie wieder aktiv sind.

Liefererfolg messen

Um ein möglichst genaues Bild der Nachrichtenzustellung zu erhalten, ist es am besten, Nachrichten nur an aktiv genutzte App-Instanzen zu senden. Dies ist besonders wichtig, wenn Sie regelmäßig Nachrichten zu Themen mit einer großen Anzahl von Abonnenten versenden; Wenn ein Teil dieser Abonnenten tatsächlich inaktiv ist, kann die Auswirkung auf Ihre Zustellstatistiken im Laufe der Zeit erheblich sein.

Bevor Sie Nachrichten an ein Token richten, sollten Sie Folgendes berücksichtigen:

  • Zeigen Google Analytics, in BigQuery erfasste Daten oder andere Tracking-Signale an, dass das Token aktiv ist?
  • Sind frühere Zustellversuche über einen längeren Zeitraum immer wieder fehlgeschlagen?
  • Wurde das Registrierungstoken auf Ihren Servern im letzten Monat aktualisiert?
  • Meldet die FCM-Daten-API bei Android-Geräten einen hohen Prozentsatz an Nachrichtenübermittlungsfehlern aufgrund droppedDeviceInactive ?

Weitere Informationen zur Zustellung finden Sie unter Grundlegendes zur Nachrichtenzustellung .