Best practice per la gestione della registrazione FCM

Se utilizzi le API FCM per creare richieste di invio a livello di programmazione, potresti scoprire che, nel tempo, sprechi risorse inviando messaggi a dispositivi inattivi con registrazioni obsolete. Questa situazione può influire sui dati di consegna dei messaggi riportati nella console Firebase o sui dati esportati in BigQuery, mostrando un calo drastico (ma non effettivamente valido) dei tassi di consegna. Questa guida illustra alcune misure che puoi adottare per garantire un targeting efficiente dei messaggi e report di consegna validi.

Registrazioni obsolete e scadute

Le registrazioni obsolete sono associate a dispositivi inattivi che non si sono connessi a FCM da più di un mese. Con il passare del tempo, è sempre meno probabile che il dispositivo si connetta di nuovo a FCM È improbabile che gli invii di messaggi e le distribuzioni di argomenti per queste registrazioni obsolete vengano mai consegnati.

Esistono diversi motivi per cui una registrazione può diventare obsoleta. Ad esempio, il dispositivo a cui è associata la registrazione potrebbe essere smarrito, distrutto o messo in magazzino e dimenticato.

Per Android, quando una registrazione è inattiva da 270 giorni, FCM la considera scaduta ed esegue la garbage collection. Una volta scaduta una registrazione, FCM la contrassegna come non valida e rifiuta gli invii. Tieni presente che gli ID di installazione Firebase (FID) sono gestiti da Firebase Installations service (FIS), non da FCM. Nel raro caso in cui un dispositivo si connetta di nuovo e l'app venga aperta dopo che è stata eseguita la garbage collection della sua registrazione, l'app client si registra di nuovo con FCM utilizzando l'FID recuperato da FIS. Tieni presente che l'FID potrebbe cambiare; per maggiori dettagli su quando vengono riemessi gli FID, consulta Gestire le installazioni Firebase.

Per altre piattaforme come iOS, FCM si basa sul servizio push sottostante (ad es. APNs), che non ha la stessa scadenza basata sull'inattività di 270 giorni. Ti consigliamo di mantenere in modo proattivo l'aggiornamento della registrazione e di rimuovere le registrazioni obsolete.

Best practice di base

Esistono alcune pratiche fondamentali che devi seguire in qualsiasi app che utilizzi FCM API per creare richieste di invio a livello di programmazione. Le principali best practice sono:

  • Recupera gli ID di installazione Firebase (FID) da FCM e memorizzali sul server dell'app. Un ruolo importante del server è tenere traccia dell'FID registrato di ogni client e mantenere un elenco aggiornato degli FID attivi. Ti consigliamo vivamente di implementare un timestamp di registrazione nel database e di aggiornarlo ogni volta che viene caricata una registrazione.
  • Mantieni l'aggiornamento della registrazione e rimuovi le registrazioni obsolete. Oltre a rimuovere le registrazioni che FCM non considera più valide, potresti monitorare altri segnali che indicano che le registrazioni sono diventate obsolete e rimuoverle in modo proattivo. Questa guida illustra alcune opzioni per raggiungere questo obiettivo.

Recuperare e memorizzare gli ID di installazione Firebase

Al primo avvio dell'app, l'FCM SDK registra l'istanza dell'app con FCM e restituisce un ID di installazione Firebase (FID). Questo è l'identificatore che devi includere nelle richieste di invio mirate dall'API o utilizzare per gli abbonamenti agli argomenti.

Ti consigliamo vivamente di salvare l'FID sul server dell'app insieme a un timestamp ogni volta che viene caricato. Aggiornando il timestamp a ogni richiesta di caricamento, il tuo server sa quando l'istanza dell'app è stata aperta e sincronizzata correttamente con il FCM backend.

A seconda che l'inizializzazione automatica sia attivata o disattivata (incluso il caso in cui non sia supportata), devi gestire la registrazione e gli aggiornamenti nel seguente modo:

  • (Consigliato) Quando l'inizializzazione automatica è attivata: l'SDK mantiene automaticamente aggiornata la registrazione e monitora le modifiche. Il onRegistered() callback viene richiamato regolarmente durante le sincronizzazioni di routine all'avvio dell'app, nonché quando si verificano modifiche dell'FID. Implementa semplicemente questo callback per caricare l'FID sul server e salvare il timestamp corrente.
  • Quando l'inizializzazione automatica è disattivata: Il onRegistered() callback non viene richiamato automaticamente all'avvio. Per monitorare le registrazioni e mantenerle aggiornate, chiama register() all'avvio dell'app, ad esempio su Android, in `onCreate()` dell'attività principale onCreate(). Una chiamata riuscita attiva la FCM registrazione procedura utilizzando l'FID e lo invia al onRegistered() callback, consentendo all'app di caricare l'FID e aggiornare il timestamp su server.

Esempio: memorizzare FID e timestamp in Cloud Firestore

Ad esempio, puoi utilizzare Cloud Firestore per memorizzare gli FID in una raccolta denominata fcmRegistrations. Ogni ID documento nella raccolta corrisponde a un ID utente e il documento memorizza l'FID corrente e il timestamp dell'ultimo aggiornamento. Utilizza la funzione set come mostrato in questo esempio Kotlin:

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)
}

Ogni volta che un ID di installazione Firebase viene registrato o aggiornato correttamente, viene richiamato il onRegistered() callback. Devi implementare questo callback per caricare l'FID e aggiornare il timestamp:

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)
}

Per le istanze in cui l'inizializzazione automatica è disattivata, chiama register() all'avvio dell'app (ad es. in onCreate()) per attivare il flusso di registrazione e la consegna dell'FID tramite onRegistered():

// 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)
        }
    }

Mantenere l'aggiornamento della registrazione e rimuovere le registrazioni obsolete

Determinare se una registrazione è aggiornata o obsoleta non è sempre semplice. Per coprire tutti i casi, devi adottare una soglia per considerare le registrazioni obsolete. Per impostazione predefinita, FCM considera una registrazione obsoleta se l'istanza dell'app non è stata connessa per un mese. È probabile che qualsiasi registrazione precedente a un mese sia un dispositivo inattivo; in caso contrario, un dispositivo attivo avrebbe aggiornato la registrazione.

A seconda del caso d'uso, un mese potrebbe essere troppo breve o troppo lungo, quindi spetta a te determinare i criteri più adatti alle tue esigenze.

Rilevare risposte non valide dal backend FCM

Assicurati di rilevare le risposte non valide da FCM e di rispondere eliminando dal sistema tutte le registrazioni note per essere non valide o scadute. Con l'API HTTP v1, questi messaggi di errore potrebbero indicare che la richiesta di invio ha come target registrazioni non valide o scadute:

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

Se hai la certezza che il payload del messaggio sia valido e ricevi una di queste risposte per una registrazione mirata, puoi eliminare in sicurezza il record di questa registrazione, perché non sarà mai più valido. Ad esempio, per eliminare le registrazioni non valide da Cloud Firestore, puoi eseguire il deployment ed eseguire una funzione come la seguente:

        // 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 restituisce una risposta non valida se una registrazione per un dispositivo Android è scaduta dopo 270 giorni di inattività o se un client ha annullato esplicitamente la registrazione. Se devi monitorare il mancato aggiornamento in modo più accurato in base alle tue definizioni, puoi rimuovere in modo proattivo le registrazioni obsolete.

Aggiornare regolarmente le registrazioni

Indipendentemente dal fatto che le registrazioni siano basate su FID o token di registrazione precedenti, il server deve sempre aggiornare il timestamp di registrazione nel database a ogni richiesta di caricamento. Questo timestamp funge da segnale per l'installazione dell'app, indicando che il client ha aperto correttamente l'app e si è sincronizzato con il FCM backend. A seconda delle API che utilizzi, implementa la strategia appropriata:

Per le app client che utilizzano le API FID, non è necessario pianificare job in background periodici nell'app client per recuperare o aggiornare le registrazioni. L'SDK si occupa automaticamente degli aggiornamenti durante l'inizializzazione automatica, fornendo regolarmente l'FID corrente corretto al onRegistered() callback durante le sincronizzazioni di routine all'avvio dell'app.

Per mantenere aggiornato il server, implementa le strategie di caricamento all'avvio descritte in Recuperare e memorizzare gli ID di installazione Firebase :

  • Inizializzazione automatica attivata: l'SDK garantisce automaticamente che l'ultimo FID venga inviato al server durante le sincronizzazioni di routine all'avvio dell'app.
  • Inizializzazione automatica disattivata o non supportata: chiama register() all'avvio dell'app (ad esempio, su Android, in onCreate()) per forzare la sequenza di registrazione e attivare la consegna dell'FID a tuo onRegistered() callback.

Queste strategie garantiscono che il server abbia sempre l'ultimo FID attivo e possa recuperare automaticamente i caricamenti non riusciti, rendendo l'applicazione altamente resiliente.

Le API token di registrazione obsolete

Se utilizzi i token di registrazione precedenti, l'SDK client non gestisce automaticamente gli aggiornamenti durante le sincronizzazioni di routine. Pertanto, ti consigliamo di recuperare e aggiornare periodicamente tutti i token di registrazione sul server. Per farlo, devi:

  • Aggiungere la logica dell'app nell'app client per recuperare il token corrente utilizzando la chiamata API appropriata (ad esempio token(completion): per le piattaforme Apple o getToken() per Android) e quindi inviare il token corrente al server dell'app per l'archiviazione (con un timestamp). Potrebbe trattarsi di un job mensile configurato per coprire tutti i client o i token.
  • Aggiungere la logica del server per aggiornare il timestamp del token a intervalli regolari, indipendentemente dal fatto che il token sia cambiato o meno.

Per un esempio di logica Android per l'aggiornamento dei token precedenti utilizzando WorkManager, consulta Gestire i token di Cloud Messaging sul blog di Firebase.

Qualunque sia il pattern di tempistica che segui, assicurati di aggiornare periodicamente i token. Una frequenza di aggiornamento di una volta al mese offre un buon equilibrio tra l'impatto sulla batteria e il rilevamento dei token di registrazione inattivi. Eseguendo questo aggiornamento, ti assicuri anche che qualsiasi dispositivo che diventa inattivo aggiorni la registrazione quando torna attivo. Non è utile eseguire l'aggiornamento con una frequenza superiore a quella settimanale.

Rimuovere le registrazioni obsolete

Prima di inviare messaggi a un dispositivo, assicurati che il timestamp della registrazione del dispositivo rientri nel periodo della finestra di obsolescenza. Ad esempio, puoi implementare Cloud Functions for Firebase per eseguire un controllo giornaliero per assicurarti che il timestamp rientri in un periodo della finestra di mancato aggiornamento definito, ad esempio const EXPIRATION_TIME = 1000 * 60 * 60 * 24 * 30; e poi rimuovere le registrazioni obsolete:

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(); }); });

Annullare l'iscrizione delle registrazioni obsolete agli argomenti

Se utilizzi gli argomenti, potresti anche voler annullare l'iscrizione delle registrazioni inattive agli argomenti a cui sono abbonate. Questa procedura prevede due passaggi:

  1. L'app deve riabbonarsi agli argomenti ogni volta che l'ID di installazione Firebase (FID) cambia. In questo modo, gli abbonamenti vengono visualizzati di nuovo automaticamente quando un'app torna attiva.
  2. Se un'istanza dell'app è inattiva per un mese (o per la tua finestra di obsolescenza), devi annullare l'iscrizione agli argomenti utilizzando l'SDK Admin Firebase per eliminare il mapping ID di installazione Firebase-argomento dal FCM backend.

Il vantaggio di questi due passaggi è che le distribuzioni avvengono più rapidamente perché ci sono meno registrazioni obsolete da distribuire e le istanze dell'app obsolete si riabbonano automaticamente una volta che sono di nuovo attive.

Misurare il successo della consegna

Per ottenere un quadro più preciso della consegna dei messaggi, è consigliabile inviare messaggi solo alle istanze dell'app utilizzate attivamente. Questo è particolarmente importante se invii regolarmente messaggi ad argomenti con un numero elevato di abbonati; se una parte di questi abbonati è in realtà inattiva, l'impatto sulle statistiche di consegna può essere significativo nel tempo.

Prima di indirizzare i messaggi a un'istanza dell'app, considera quanto segue:

Per ulteriori informazioni sulla consegna, consulta Informazioni sulla consegna dei messaggi.