Best Practices für die Verwaltung der FCM-Registrierung

Wenn Sie FCM-APIs verwenden, um Send-Anfragen programmatisch zu erstellen, verschwenden Sie möglicherweise im Laufe der Zeit Ressourcen, 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 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

Abgelaufene 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 verschiedene Gründe, warum eine Registrierung veraltet sein kann. Das Gerät, mit dem die Registrierung verknüpft ist, kann beispielsweise verloren gehen, zerstört werden oder eingelagert und vergessen werden.

Wenn eine Registrierung unter Android 270 Tage lang inaktiv war, wird sie von FCM als abgelaufen betrachtet und gelöscht. Sobald eine Registrierung abgelaufen ist, markiert 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.

Bei 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 Ihnen, die Registrierung proaktiv auf dem neuesten Stand zu halten und veraltete Registrierungen zu entfernen.

Grundlegende Best Practices

Es gibt einige grundlegende Vorgehensweisen, die Sie in jeder App befolgen sollten, in der FCM-APIs verwendet werden, 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 ist es, 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 jedes Mal 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 beschrieben, die Sie dafür haben.

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 gezielten Sendeanfragen über die API angeben oder für Themenabos verwenden müssen.

Wir empfehlen dringend, die FID 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 (oder nicht unterstützt wird), sollten Sie die Registrierung und Updates so handhaben:

  • (Empfohlen) Wenn die automatische Initialisierung aktiviert ist:Das SDK sorgt automatisch dafür, dass die Registrierung aktuell bleibt, 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 onRegistered()-Callback 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 die FCM-Registrierung mit der FID aus und stellt sie Ihrem onRegistered()-Callback zur Verfügung. So kann Ihre App die FID hochladen und den Zeitstempel auf Ihrem Server aktualisieren.

Beispiel: Speichern von Store-FIDs 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. Im Dokument werden die aktuelle FID und der Zeitstempel der letzten Aktualisierung gespeichert. 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 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 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, beziehen sich wahrscheinlich auf inaktive Geräte. Aktive Geräte hätten ihre Registrierung aktualisiert.

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 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 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 beim Starten der App bereit.

Damit Ihr Server auf dem neuesten Stand bleibt, implementieren Sie die in Firebase-Installations-IDs abrufen und speichern beschriebenen Uploadstrategien für den 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()-Methode der Hauptaktivität), um die Registrierungssequenz zu erzwingen und die FID-Übermittlung an Ihren onRegistered()-Callback auszulösen.

Diese Strategien sorgen dafür, 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 mit einem Zeitstempel an Ihren App-Server zu senden, damit es dort gespeichert wird. 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 aller Geräte, die inaktiv werden, aktualisiert wird, wenn sie wieder aktiv werden. Eine Aktualisierung, die häufiger als wöchentlich erfolgt, 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 die Aktualität liegt. Sie könnten 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, für die sie registriert sind, abmelden. Dazu sind zwei Schritte erforderlich:

  1. Ihre App sollte sich immer dann neu für Themen registrieren, 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 (oder innerhalb Ihres eigenen Zeitfensters für Inaktivität) 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 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.

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 Zustellungsstatistiken auswirken.

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

  • Wird in Google Analytics, in BigQuery erfassten Daten oder anderen Tracking-Signalen angezeigt, 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 Fehlern bei der Nachrichtenzustellung aufgrund von droppedDeviceInactive gemeldet?

Weitere Informationen zur Zustellung finden Sie unter Informationen zur Nachrichtenzustellung.