Best practice per la gestione dei token di registrazione FCM

Se utilizzi le API FCM per creare richieste di invio a livello di codice, potresti scoprire che, nel tempo, stai sprecando risorse inviando messaggi a dispositivi inattivi con token di registrazione obsoleti. Questa situazione può influire sui dati di consegna dei messaggi riportati nella console Firebase o sui dati esportati in BigQuery, manifestandosi come un calo drastico (ma non effettivamente valido) dei tassi di consegna. In questa guida vengono illustrate alcune misure che è possibile adottare per garantire un targeting efficiente dei messaggi e rapporti di consegna validi.

Token di registrazione obsoleti e scaduti

I token di registrazione obsoleti sono token associati a dispositivi inattivi che non si sono connessi a FCM per più di un mese. Con il passare del tempo, diventa sempre meno probabile che il dispositivo si ricolleghi a FCM. È improbabile che gli invii di messaggi e i fanout degli argomenti per questi token obsoleti vengano mai recapitati.

Esistono diversi motivi per cui un token può diventare obsoleto. Ad esempio, il dispositivo a cui è associato il token potrebbe essere perso, distrutto o archiviato e dimenticato.

Quando i token obsoleti raggiungono i 270 giorni di inattività, FCM li considererà scaduti . Una volta scaduto un token, FCM lo contrassegna come non valido e rifiuta gli invii ad esso inviati. Tuttavia, FCM emette un nuovo token per l'istanza dell'app nel raro caso in cui il dispositivo si riconnetta e l'app venga aperta.

Migliori pratiche di base

Esistono alcune pratiche fondamentali da seguire in qualsiasi app che utilizza le API FCM per creare richieste di invio a livello di codice. Le principali buone pratiche sono:

  • Recupera i token di registrazione da FCM e archiviali sul tuo server. Un ruolo importante per il server è tenere traccia del token di ciascun client e mantenere un elenco aggiornato dei token attivi. Ti consigliamo vivamente di implementare un timestamp del token nel tuo codice e nei tuoi server e di aggiornare questo timestamp a intervalli regolari.
  • Mantieni la freschezza dei token e rimuovi i token obsoleti. Oltre a rimuovere i token che FCM non considera più validi, potresti voler monitorare altri segnali che indicano che i token sono diventati obsoleti e rimuoverli in modo proattivo. Questa guida illustra alcune delle opzioni per raggiungere questo obiettivo.

Recupera e archivia i token di registrazione

All'avvio iniziale della tua app, l'SDK FCM genera un token di registrazione per l'istanza dell'app client. Questo è il token che devi includere nelle richieste di invio mirate dall'API o aggiungere alle sottoscrizioni agli argomenti per la destinazione degli argomenti.

Consigliamo vivamente alla tua app di recuperare questo token all'avvio iniziale e di salvarlo sul server dell'app insieme a un timestamp . Questo timestamp deve essere implementato dal tuo codice e dai tuoi server, poiché non ti viene fornito dagli SDK di FCM.

Inoltre, è importante salvare il token sul server e aggiornare il timestamp ogni volta che cambia, ad esempio quando:

  • L'app viene ripristinata su un nuovo dispositivo
  • L'utente disinstalla o reinstalla l'app
  • L'utente cancella i dati dell'app
  • L'app diventa nuovamente attiva dopo che FCM ha scaduto il token esistente

Esempio: archivia token e timestamp in Cloud Firestore

Ad esempio, potresti utilizzare Cloud Firestore per archiviare i token in una raccolta denominata fcmTokens . Ogni ID documento nella raccolta corrisponde a un ID utente e il documento memorizza il token di registrazione corrente e il timestamp dell'ultimo aggiornamento. Utilizza la funzione set come mostrato in questo esempio di Kotlin:

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

Ogni volta che un token viene recuperato, viene archiviato in Cloud Firestore chiamando sendTokenToServer :

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

Mantieni la freschezza dei token e rimuovi i token obsoleti

Determinare se un token è nuovo o obsoleto non è sempre semplice. Per coprire tutti i casi, dovresti adottare una soglia per quando consideri i token obsoleti. Per impostazione predefinita, FCM considera obsoleto un token se l'istanza dell'app non si è connessa per un mese. È probabile che qualsiasi token più vecchio di un mese sia un dispositivo inattivo; altrimenti un dispositivo attivo avrebbe aggiornato il proprio token.

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

Rileva risposte token non valide dal backend FCM

Assicurati di rilevare le risposte dei token non validi da FCM e rispondi eliminando dal tuo sistema tutti i token di registrazione noti per essere non validi o scaduti. Con l'API HTTP v1, questi messaggi di errore potrebbero indicare che la tua richiesta di invio aveva come target token non validi o scaduti:

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

Se sei sicuro che il payload del messaggio sia valido e ricevi una di queste risposte per un token mirato, è sicuro eliminare il record di questo token, poiché non sarà mai più valido. Ad esempio, per eliminare token non validi da Cloud Firestore, potresti distribuire ed eseguire una funzione come la seguente:

    // 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 restituirà una risposta token non valida solo se un token è scaduto dopo 270 giorni o se un client ha annullato esplicitamente la registrazione. Se è necessario monitorare in modo più accurato lo stato di obsolescenza in base alle proprie definizioni, è possibile rimuovere in modo proattivo i token di registrazione obsoleti .

Aggiorna i token regolarmente

Ti consigliamo di recuperare e aggiornare periodicamente tutti i token di registrazione sul tuo server. Ciò richiede di:

  • Aggiungi la logica dell'app nell'app client per recuperare il token corrente utilizzando la chiamata API appropriata (come token(completion): per piattaforme Apple o getToken() per Android) e quindi invia il token corrente al server dell'app per l'archiviazione (con un marca temporale). Potrebbe trattarsi di un lavoro mensile configurato per coprire tutti i client o token.
  • Aggiungi 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 utilizzando WorkManager , consulta Gestione dei token di messaggistica cloud sul blog Firebase.

Qualunque sia il modello temporale che segui, assicurati di aggiornare periodicamente i token. Una frequenza di aggiornamento di una volta al mese raggiunge un buon equilibrio tra l'impatto sulla batteria e il rilevamento di token di registrazione inattivi. Eseguendo questo aggiornamento, ti assicuri anche che qualsiasi dispositivo che diventa inattivo aggiornerà la sua registrazione quando tornerà attivo. Non vi è alcun vantaggio nell'eseguire l'aggiornamento con una frequenza superiore a quella settimanale.

Rimuovere i token di registrazione obsoleti

Prima di inviare messaggi a un dispositivo, assicurati che il timestamp del token di registrazione del dispositivo rientri nel periodo della finestra di inattività. Ad esempio, potresti implementare Cloud Functions for Firebase per eseguire un controllo giornaliero per garantire che il timestamp rientri in un periodo di finestra di obsolescenza definito come const EXPIRATION_TIME = 1000 * 60 * 60 * 24 * 30; e quindi rimuovere i token obsoleti:

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

Annulla l'iscrizione ai token obsoleti dagli argomenti

Se utilizzi argomenti, potresti anche voler annullare la registrazione dei token obsoleti dagli argomenti a cui sono iscritti. Ciò comporta due passaggi:

  1. La tua app dovrebbe iscriversi nuovamente agli argomenti una volta al mese e ogni volta che cambia il token di registrazione. Ciò costituisce una soluzione di autoriparazione, in cui gli abbonamenti riappaiono automaticamente quando un'app diventa di nuovo attiva.
  2. Se un'istanza dell'app rimane inattiva per un mese (o per un periodo di inattività), dovresti annullarne l'iscrizione agli argomenti utilizzando Firebase Admin SDK per eliminare la mappatura tra token e argomento dal backend FCM.

Il vantaggio di questi due passaggi è che i fanout verranno eseguiti più rapidamente poiché ci sono meno token obsoleti su cui eseguire il fanout e le istanze dell'app obsolete verranno automaticamente sottoscritte nuovamente una volta che saranno nuovamente attive.

Misura il successo della consegna

Per ottenere un quadro più accurato della consegna dei messaggi, è meglio inviare messaggi solo alle istanze dell'app utilizzate attivamente. Ciò è particolarmente importante se invii regolarmente messaggi ad argomenti con un gran numero di iscritti; se una parte di questi iscritti è effettivamente inattiva, l'impatto sulle statistiche di consegna può essere significativo nel tempo.

Prima di indirizzare i messaggi a un token, considera:

  • Google Analytics, i dati acquisiti in BigQuery o altri segnali di monitoraggio indicano che il token è attivo?
  • I precedenti tentativi di consegna sono falliti costantemente per un periodo di tempo?
  • Il token di registrazione è stato aggiornato sui tuoi server nell'ultimo mese?
  • Per i dispositivi Android, l' API FCM Data segnala un'elevata percentuale di errori di recapito dei messaggi dovuti a droppedDeviceInactive ?

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