Best Practices für die Verwaltung der FCM-Registrierung

Wenn Sie FCM APIs verwenden, um Sendeanfragen programmatisch zu erstellen, stellen Sie möglicherweise mit der Zeit fest, dass Sie Ressourcen verschwenden, indem Sie Nachrichten an inaktive Geräte mit veralteten Registrierungen senden. Diese Situation kann sich auf die Daten zur Nachrichtenzustellung auswirken, die in der Firebase Konsole gemeldet oder nach BigQuery exportiert wurden. Dort wird dann ein drastischer (aber nicht tatsächlich gültiger) Rückgang der Zustellungsraten angezeigt. In dieser Anleitung werden einige Maßnahmen beschrieben, die Sie ergreifen können, um eine effiziente Nachrichtenzustellung und eine gültige Zustellungsberichterstattung zu gewährleisten.

Veraltete und abgelaufene Registrierungen

Veraltete Registrierungen sind mit inaktiven Geräten verknüpft, die seit über einem Monat keine Verbindung zu FCM hergestellt haben. Mit der Zeit wird es immer unwahrscheinlicher, dass sich das Gerät jemals wieder mit FCM verbindet. Nachrichten, die an diese veralteten Registrierungen gesendet werden, und Topic-Fanouts werden wahrscheinlich nie zugestellt.

Es gibt mehrere Gründe, warum eine Registrierung veraltet sein kann. Beispielsweise kann das Gerät, mit dem die Registrierung verknüpft ist, verloren gegangen, zerstört oder eingelagert und vergessen worden sein.

Wenn eine Registrierung für Android 270 Tage lang inaktiv war, FCM betrachtet sie als abgelaufen und führt eine Garbage Collection durch. Sobald eine Registrierung abgelaufen ist, FCM markiert es als ungültig und lehnt Sendungen an es ab. Firebase-Installations-IDs (FIDs) werden vomFirebase Installations Service (FIS) und nicht von FCM verwaltet. In dem seltenen Fall, dass sich ein Gerät wieder verbindet und die App geöffnet wird, nachdem die Registrierung per Garbage Collection entfernt wurde, registriert sich die Client-App mit der vom FIS abgerufenen FID wieder bei FCM. Die FID kann sich ändern. Weitere Informationen dazu, wann FIDs neu ausgestellt werden, finden Sie unter Firebase-Installationen verwalten.

Bei anderen Plattformen wie iOS verwendet FCM den zugrunde liegenden Push Dienst (z.B. APNs), bei dem die Registrierung nicht nach 270 Tagen Inaktivität abläuft. Wir empfehlen, die Registrierungen proaktiv auf dem neuesten Stand zu halten und veraltete Registrierungen zu entfernen.

Grundlegende Best Practices

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

  • Firebase-Installations-IDs (FIDs) von FCM abrufen und auf Ihrem App-Server speichern. Eine wichtige Aufgabe des Servers besteht darin, die registrierte FID jedes Clients zu verfolgen und eine aktuelle Liste der aktiven FIDs zu führen. Wir empfehlen dringend, einen Registrierungszeitstempel in Ihrer Datenbank zu implementieren und ihn immer zu aktualisieren, wenn eine Registrierung hochgeladen wird.
  • Registrierungen auf dem neuesten Stand halten und veraltete Registrierungen entfernen Neben dem Entfernen von Registrierungen, die FCM nicht mehr als gültig betrachtet, sollten Sie auch andere Anzeichen dafür beobachten, dass Registrierungen veraltet sind, und sie proaktiv entfernen. In dieser Anleitung werden einige Optionen dafür beschrieben.

Firebase-Installations-IDs abrufen und speichern

Beim ersten Start Ihrer App registriert das FCM SDK die App-Instanz bei FCM und gibt eine Firebase-Installations-ID (FID) zurück. Diese ID müssen Sie in gezielten Sendeanfragen von der API angeben oder für Topic-Abos verwenden.

Wir empfehlen dringend, die FID zusammen mit einem Zeitstempel auf Ihrem App-Server zu speichern, wenn sie hochgeladen wird. Wenn Sie den Zeitstempel bei jeder Uploadanfrage aktualisieren, weiß Ihr Server, wann die App-Instanz zuletzt geöffnet und erfolgreich mit dem FCM Backend synchronisiert wurde.

Je nachdem, ob die automatische Initialisierung aktiviert oder deaktiviert ist (einschließlich nicht unterstützt), sollten Sie Registrierungen und Aktualisierungen so handhaben:

  • (Empfohlen) Wenn die automatische Initialisierung aktiviert ist:Das SDK hält die Registrierung automatisch auf dem neuesten Stand und überwacht Änderungen. Der onRegistered() Callback wird bei routinemäßigen Synchronisierungen beim Start der App sowie bei FID-Änderungen regelmäßig aufgerufen. Implementieren Sie diesen Callback einfach, um die FID auf Ihren Server hochzuladen und den aktuellen Zeitstempel zu speichern.
  • Wenn die automatische Initialisierung deaktiviert ist: Der onRegistered() Callback wird beim Start nicht automatisch aufgerufen. Um Registrierungen zu verfolgen und auf dem neuesten Stand zu halten, rufen Sie beim Start der App register() auf, z. B. unter Android in der onCreate()-Methode der Hauptaktivität. Ein erfolgreicher Aufruf löst den FCM Registrierungsprozess mit der FID aus und liefert sie an Ihren onRegistered() Callback. So kann Ihre App die FID hochladen und den Zeitstempel auf Ihrem Server aktualisieren.

Beispiel: FIDs und Zeitstempel in Cloud Firestore speichern

Sie können beispielsweise Cloud Firestore verwenden, um FIDs in einer Sammlung namens fcmRegistrations zu speichern. Jede Dokument-ID in der Sammlung entspricht einer Nutzer-ID und das Dokument speichert die aktuelle FID und den Zeitstempel der letzten Aktualisierung. Verwenden Sie die Funktion set, wie in diesem Kotlin-Beispiel gezeigt:

private fun sendRegistrationToServer(installationId: String?) {
    // If you're running your own server, call API to send registration details and today's date for the user

    // Example shown uses Firestore
    // Add FID and timestamp to Firestore for this user
    val deviceFid = hashMapOf(
        "installationId" to installationId,
        "timestamp" to FieldValue.serverTimestamp(),
    )
    // Get user ID from Firebase Auth or your own server
    Firebase.firestore.collection("fcmRegistrations").document("myuserid")
        .set(deviceFid)
}

Immer wenn eine Firebase-Installations-ID erfolgreich registriert oder aktualisiert wird, wird der onRegistered() Callback aufgerufen. Sie sollten diesen Callback implementieren, um die FID hochzuladen und den Zeitstempel zu aktualisieren:

override fun onRegistered(installationId: String) {
    Log.d(TAG, "Registered installation ID: $installationId")

    // Send the Firebase Installation ID (FID) to your app server. Your app
    // server should save the FID and update the timestamp upon receipt.
    sendRegistrationToServer(installationId)
}

Bei Instanzen, bei denen die automatische Initialisierung deaktiviert ist, rufen Sie register() beim Start der App auf (z.B. in onCreate()), um den Registrierungsablauf und die FID Übermittlung über onRegistered()auszulösen:

// Trigger manual registration if auto-initialization is turned off.
FirebaseMessaging.getInstance().register()
    .addOnCompleteListener(this) { task ->
        if (task.isSuccessful) {
            // The registration callback onRegistered() will be invoked with the current FID.
        } else {
            Log.w(TAG, "Failed to register with Firebase Cloud Messaging", task.exception)
        }
    }

Registrierungen auf dem neuesten Stand halten und veraltete Registrierungen entfernen

Es ist nicht immer einfach zu bestimmen, ob eine Registrierung auf dem neuesten Stand oder veraltet ist. Um alle Fälle abzudecken, sollten Sie einen Schwellenwert festlegen, ab dem Sie Registrierungen als veraltet betrachten. Standardmäßig betrachtet FCM eine Registrierung als veraltet, wenn sich die zugehörige App-Instanz seit einem Monat nicht mehr verbunden hat. Jede Registrierung, die älter als einen Monat ist, bezieht sich wahrscheinlich auf ein inaktives Gerät. Ein aktives Gerät hätte seine Registrierung 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 Antworten vom FCM Backend erkennen

Sie müssen ungültige Antworten von FCM erkennen und darauf reagieren, indem Sie alle Registrierungen, die bekanntermaßen ungültig sind oder abgelaufen sind, aus Ihrem System löschen. Bei der HTTP v1 API können diese Fehlermeldungen darauf hinweisen, dass Ihre Sendeanfrage auf ungültige oder abgelaufene Registrierungen ausgerichtet war:

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

Wenn Sie sicher sind, dass die Nachrichten-Payload gültig ist, und Sie eine dieser Antworten für eine gezielte Registrierung erhalten, können Sie Ihren Eintrag für diese Registrierung löschen, da sie nie wieder gültig sein wird. Um beispielsweise ungültige Registrierungen aus Cloud Firestore zu löschen, können Sie eine Funktion wie die folgende bereitstellen und ausführen:

        // Firebase Installation ID comes from the client FCM SDKs
        const firebaseInstallationId = 'YOUR_FIREBASE_INSTALLATION_ID';

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

        // Send message to device with provided Firebase Installation ID
        getMessaging().send(message)
        .then((response) => {
            // Response is a message ID string.
        })
        .catch((error) => {
            // Delete registration for user if error code is UNREGISTERED or INVALID_ARGUMENT.
            if (error.errorCode == "messaging/registration-token-not-registered") {
                // If you're running your own server, call API to delete the registration for the user
                // Example shown uses Firestore
                // Get user ID from Firebase Auth or your own server
                Firebase.firestore.collection("fcmRegistrations").document(user.uid).delete()
            }
        });

FCM gibt eine ungültige Antwort zurück, wenn eine Registrierung für ein Android Gerät nach 270 Tagen Inaktivität abgelaufen ist oder wenn ein Client die Registrierung explizit aufgehoben hat. Wenn Sie die Veraltung genauer nach Ihren eigenen Definitionen verfolgen möchten, können Sie veraltete Registrierungen proaktiv entfernen.

Registrierungen regelmäßig aktualisieren

Unabhängig davon, ob Ihre Registrierungen auf FIDs oder älteren Registrierungstokens basieren, sollte Ihr Server den Zeitstempel der Registrierung in Ihrer Datenbank bei jeder Uploadanfrage aktualisieren. Dieser Zeitstempel dient als Signal für die App-Installation und zeigt an, dass der Client die App erfolgreich geöffnet und mit dem FCM Backend synchronisiert hat. Implementieren Sie je nach den verwendeten APIs die entsprechende Strategie:

Bei Client-Apps, die die FID APIs verwenden, müssen Sie keine regelmäßigen Hintergrundjobs in Ihrer Client-App planen, um Registrierungen abzurufen oder zu aktualisieren. Das SDK kümmert sich automatisch um Aktualisierungen bei der automatischen Initialisierung und liefert bei routinemäßigen Synchronisierungen beim Start der App regelmäßig die richtige aktuelle FID an Ihren onRegistered() Callback.

Um Ihren Server auf dem neuesten Stand zu halten, implementieren Sie die in Firebase-Installations -IDs abrufen und speichern beschriebenen Strategien für das Hochladen beim Start:

  • Automatische Initialisierung aktiviert:Das SDK sorgt automatisch dafür, dass die neueste FID bei routinemäßigen Synchronisierungen beim Start der App an Ihren Server gesendet wird.
  • Automatische Initialisierung deaktiviert oder nicht unterstützt: Rufen Sie beim Start der App register() auf (z. B. unter Android in der onCreate()-Methode der Hauptaktivität), um die Registrierungssequenz zu erzwingen und die FID-Übermittlung an Ihren onRegistered() -Callback auszulösen.

Mit diesen Strategien ist garantiert, dass Ihr Server immer die neueste aktive FID hat und sich automatisch von fehlgeschlagenen Uploads erholen kann. Dadurch ist die Anwendung sehr robust.

Die verworfenen Registrierungstoken APIs

Wenn Sie ältere Registrierungstokens verwenden, werden Aktualisierungen bei routinemäßigen Synchronisierungen nicht automatisch vom Client SDK verwaltet. Daher empfehlen wir, alle Registrierungstokens regelmäßig auf Ihrem Server abzurufen und zu aktualisieren. Dazu müssen Sie Folgendes tun:

  • Fügen Sie in Ihrer Client-App 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 das aktuelle Token dann mit einem Zeitstempel zur Speicherung an Ihren App-Server zu senden. Dies kann ein monatlicher Job sein, der für alle Clients oder Tokens konfiguriert ist.
  • 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 Android-Logik zum Aktualisieren älterer Tokens mit WorkManager, finden Sie im Firebase-Blog unter Managing Cloud Messaging Tokens.

Unabhängig davon, welchem Zeitplan Sie folgen, müssen Sie Tokens regelmäßig aktualisieren. Eine Aktualisierungshäufigkeit von einmal pro Monat bietet ein gutes Gleichgewicht zwischen den Auswirkungen auf den Akku und dem Erkennen inaktiver Registrierungstokens. Durch diese Aktualisierung wird auch sichergestellt, dass jedes Gerät, das inaktiv wird, seine Registrierung aktualisiert, wenn es wieder aktiv wird. Eine häufigere Aktualisierung als einmal pro Woche bringt keine Vorteile.

Veraltete Registrierungen entfernen

Bevor Sie Nachrichten an ein Gerät senden, prüfen Sie, ob der Zeitstempel der Registrierung des Geräts innerhalb des Zeitraums für veraltete Registrierungen liegt. Sie können beispielsweise Cloud Functions for Firebase implementieren, um täglich zu prüfen, ob der Zeitstempel innerhalb eines definierten Zeitraums für veraltete Registrierungen liegt, z. B. const EXPIRATION_TIME = 1000 * 60 * 60 * 24 * 30;, und dann veraltete Registrierungen zu entfernen:

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

Veraltete Registrierungen von Topics abmelden

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

  1. Ihre App sollte Topics neu abonnieren, wenn sich die Firebase-Installations-ID (FID) ändert. So werden die Abos automatisch wieder angezeigt, wenn eine App wieder aktiv wird.
  2. Wenn eine App-Instanz einen Monat lang inaktiv ist (oder innerhalb Ihres eigenen Zeitraums für veraltete Registrierungen), sollten Sie sie von Topics abmelden. Verwenden Sie dazu das Firebase Admin SDK , um die Zuordnung von Firebase-Installations-ID zu Topic aus dem FCM Backend zu löschen.

Der Vorteil dieser beiden Schritte besteht darin, dass Ihre Fanouts schneller erfolgen, da es weniger veraltete Registrierungen gibt, an die Fanouts gesendet werden müssen. Außerdem werden Ihre veralteten App-Instanzen automatisch neu abonniert, sobald sie wieder aktiv sind.

Zustellungserfolg messen

Um ein möglichst genaues Bild der Nachrichtenzustellung zu erhalten, sollten Sie Nachrichten nur an aktiv verwendete App-Instanzen senden. Das ist besonders wichtig, wenn Sie regelmäßig Nachrichten an Topics 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 an eine App-Instanz senden, sollten Sie Folgendes prüfen:

  • Deuten Google Analytics, in BigQuery erfasste Daten oder andere Tracking-Signale darauf hin, dass die Registrierung aktiv ist?
  • Sind frühere Zustellungsversuche über einen bestimmten Zeitraum hinweg immer wieder fehlgeschlagen?
  • Wurde die Firebase-Installations-ID in den letzten Monat auf Ihren Servern aktualisiert?
  • Meldet die FCM Data API für Android-Geräte einen hohen Prozentsatz an Fehlern bei der Nachrichtenzustellung aufgrund von droppedDeviceInactive?

Weitere Informationen zur Zustellung finden Sie unter Informationen zur Nachrichtenzustellung.