Best Practices für die Verwaltung der FCM-Registrierung

Wenn Sie FCM-APIs verwenden, um Sendeanfragen programmatisch zu erstellen, verschwenden Sie möglicherweise im Laufe der Zeit Ressourcen, indem Sie Nachrichten an inaktive Geräte mit veralteten Registrierungen senden. Dies kann sich auf die Daten zur Nachrichtenzustellung auswirken, die in der Firebase-Konsole gemeldet oder in BigQuery exportiert werden. Dort wird dann ein drastischer (aber nicht wirklich gültiger) Rückgang der Zustellungsraten angezeigt. In diesem Leitfaden werden einige Maßnahmen beschrieben, die Sie ergreifen können, um eine effiziente Ausrichtung von Nachrichten und eine gültige Zustellungsberichterstellung 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. Nachrichtensendungen und Topic-Fanouts für diese inaktiven Registrierungen 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 gehen, zerstört werden oder in einem Lagerraum vergessen werden.

Bei Android gilt eine Registrierung nach 270 Tagen Inaktivität als abgelaufen und wird von FCM gelöscht. Wenn eine Registrierung abgelaufen ist, kennzeichnet FCM sie als ungültig und lehnt Sendungen an sie ab. Firebase-Installations-IDs (FIDs) werden vom Firebase Installations-Dienst (FIS) und nicht von FCM verwaltet. In dem seltenen Fall, dass ein Gerät wieder verbunden wird und die App geöffnet wird, nachdem die Registrierung des Geräts gelöscht wurde, registriert sich die Client-App mit der FID, die von FIS abgerufen wurde, noch einmal bei FCM. Die FID kann sich ändern. Weitere Informationen dazu, wann FIDs neu ausgestellt werden, finden Sie unter Firebase-Installationen verwalten.

Auf anderen Plattformen wie iOS basiert FCM auf dem zugrunde liegenden Push-Dienst (z.B. APNs), der nicht denselben Ablauf nach 270 Tagen Inaktivität hat. Wir empfehlen, Registrierungen proaktiv zu aktualisieren und veraltete Registrierungen zu entfernen.

Grundlegende Best Practices

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

  • Firebase-Installations-IDs (FIDs) aus FCM abrufen und auf Ihrem App-Server speichern: Eine wichtige Aufgabe des Servers besteht darin, die registrierte FID jedes Clients zu erfassen und eine aktualisierte Liste der aktiven FIDs zu führen. Wir empfehlen dringend, einen Registrierungszeitstempel in Ihrer Datenbank zu implementieren und ihn immer dann zu aktualisieren, wenn eine Registrierung hochgeladen wird.
  • Registrierungen aktuell halten und alte Registrierungen entfernen: Neben dem Entfernen von Registrierungen, die FCM nicht mehr als gültig betrachtet, sollten Sie auch auf andere Anzeichen achten, dass Registrierungen veraltet sind, und sie proaktiv entfernen. In diesem Leitfaden 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. Dies ist die Kennung, die Sie in gezielte Sendeanfragen über die API einfügen oder für Themenabos verwenden müssen.

Wir empfehlen dringend, die Geräte-ID zusammen mit einem Zeitstempel auf Ihrem App-Server zu speichern, wenn sie hochgeladen wird. Durch das Aktualisieren des Zeitstempels bei jeder Uploadanfrage 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 die Registrierung und Updates so handhaben:

  • (Empfohlen) Wenn die automatische Initialisierung aktiviert ist:Das SDK aktualisiert die Registrierung automatisch und überwacht Änderungen. Der Callback onRegistered() wird regelmäßig bei routinemäßigen Synchronisierungen beim Start der App sowie bei Änderungen der FID 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 Callback onRegistered() wird beim Start nicht automatisch aufgerufen. Um Registrierungen zu erfassen und auf dem neuesten Stand zu halten, rufen Sie register() beim Start der App auf, z. B. unter Android in der onCreate() der Hauptaktivität. Ein erfolgreicher Aufruf löst den FCM-Registrierungsprozess mit der FID aus und stellt sie über den onRegistered()-Callback für Ihre App bereit. So kann Ihre App die FID hochladen und den Zeitstempel auf Ihrem Server aktualisieren.

Beispiel: Speichern von Geräte-IDs und Zeitstempeln in Cloud Firestore

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 Callback onRegistered() aufgerufen. Sie sollten diesen Callback implementieren, um die Geräte-ID 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 beim Start der App (z.B. in onCreate()) register() auf, 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 aktuell halten und veraltete Registrierungen entfernen

Es ist nicht immer einfach, festzustellen, ob eine Registrierung neu oder veraltet ist. Um alle Fälle abzudecken, sollten Sie einen Schwellenwert festlegen, ab dem Registrierungen als veraltet gelten. Standardmäßig betrachtet FCM eine Registrierung als veraltet, wenn die zugehörige App-Instanz seit einem Monat keine Verbindung mehr hergestellt hat. Registrierungen, die älter als einen Monat sind, stammen wahrscheinlich von inaktiven Geräten. Aktive Geräte würden ihre Registrierung aktualisieren.

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

Ungültige Antworten vom FCM-Backend erkennen

Achten Sie darauf, ungültige Antworten von FCM zu erkennen und darauf zu reagieren, indem Sie alle Registrierungen, die als ungültig bekannt 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 Nutzlast der Nachricht gültig ist und Sie eine dieser Antworten für eine gezielte Registrierung erhalten, können Sie den entsprechenden Datensatz löschen, da er nie wieder gültig sein wird. Wenn Sie beispielsweise ungültige Registrierungen aus Cloud Firestore löschen möchten, 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 die 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 Aktualität genauer nach Ihren eigenen Definitionen erfassen möchten, können Sie veraltete Registrierungen proaktiv entfernen.

Registrierungen regelmäßig aktualisieren

Unabhängig davon, ob Ihre Registrierungen auf FIDs oder Legacy-Registrierungstokens basieren, sollte Ihr Server den Registrierungszeitstempel in Ihrer Datenbank bei jeder Uploadanfrage aktualisieren. Dieser Zeitstempel dient als Signal für die App-Installation. Er gibt 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 stellt regelmäßig die richtige aktuelle FID für Ihren onRegistered()-Callback bei routinemäßigen Synchronisierungen während des App-Starts bereit.

Damit Ihr Server auf dem neuesten Stand bleibt, implementieren Sie die in Firebase-Installations-IDs abrufen und speichern beschriebenen Strategien für den Upload beim Start:

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

Diese Strategien garantieren, dass Ihr Server immer die aktuelle aktive FID hat und sich automatisch von fehlgeschlagenen Uploads erholen kann. Dadurch ist die Anwendung sehr robust.

Die verworfenen APIs für Registrierungstokens

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

  • Fügen Sie 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 zur Speicherung (mit einem Zeitstempel) an Ihren App-Server zu senden. Das kann ein monatlicher Job sein, der für alle Kunden 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 die Android-Logik zum Aktualisieren von Legacy-Tokens mit WorkManager finden Sie im Firebase-Blog unter Cloud Messaging-Tokens verwalten.

Unabhängig davon, welchem Zeitmuster Sie folgen, sollten Sie Tokens regelmäßig aktualisieren. Eine Updatehäufigkeit von einmal pro Monat bietet ein gutes Gleichgewicht zwischen Akkuverbrauch und Erkennung inaktiver Registrierungstokens. Durch diese Aktualisierung wird auch dafür gesorgt, dass die Registrierung jedes Geräts, das inaktiv wird, aktualisiert wird, wenn es wieder aktiv wird. Eine häufigere Aktualisierung als wöchentlich bietet keine Vorteile.

Alte 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 Daten 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 Daten wie const EXPIRATION_TIME = 1000 * 60 * 60 * 24 * 30; liegt, und dann veraltete Registrierungen 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(); }); });

Inaktive Registrierungen für Themen abmelden

Wenn Sie Themen verwenden, sollten Sie auch alte Registrierungen für die Themen abmelden, für die sie registriert sind. Dazu sind zwei Schritte erforderlich:

  1. Ihre App sollte Themen neu abonnieren, wenn sich die Firebase-Installations-ID (FID) ändert. Dadurch werden die Abos automatisch wieder angezeigt, wenn eine App wieder aktiv wird.
  2. Wenn eine App-Instanz einen Monat lang (oder entsprechend Ihrem eigenen Inaktivitätszeitraum) inaktiv ist, sollten Sie sie mit dem Firebase Admin SDK von Themen abmelden, um die Zuordnung von Firebase-Installations-ID zu Thema aus dem FCM-Backend zu löschen.

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

Liefererfolg 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 Themen mit einer großen Anzahl von Abonnenten senden. Wenn ein Teil dieser Abonnenten tatsächlich inaktiv ist, kann sich das im Laufe der Zeit erheblich auf Ihre Zustellstatistiken auswirken.

Bevor Sie Nachrichten auf eine App-Instanz ausrichten, sollten Sie Folgendes beachten:

  • Gibt es in Google Analytics, in BigQuery erfassten Daten oder anderen Tracking-Signalen Hinweise darauf, dass die Registrierung aktiv ist?
  • Sind frühere Zustellversuche über einen längeren Zeitraum hinweg immer wieder fehlgeschlagen?
  • Wurde die Firebase-Installations-ID in den letzten Monaten auf Ihren Servern aktualisiert?
  • Wird für Android-Geräte in der FCM Data API ein hoher Prozentsatz von fehlgeschlagenen Nachrichtenübermittlungen aufgrund von droppedDeviceInactive gemeldet?

Weitere Informationen zur Zustellung finden Sie unter Nachrichtenzustellung.