Best practice per la gestione dei token di registrazione FCM

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

Token di registrazione obsoleti e scaduti

I token di registrazione obsoleti sono token associati a dispositivi inattivi che non si connettono a FCM da più di un mese. Con il passare del tempo, diventa sempre meno probabile che il dispositivo si connetta di nuovo a FCM. È improbabile che i messaggi e le distribuzioni 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 smarrito, distrutto o riposto e dimenticato.

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

Best practice di base

Esistono alcune pratiche fondamentali da seguire in qualsiasi app che utilizza le API FCM per creare richieste di invio in modo programmatico. Le best practice principali sono:

  • Recupera i token di registrazione da FCM e memorizzali sul tuo server. Un ruolo importante del server è tenere traccia del token di ogni client e mantenere un elenco aggiornato dei token attivi. Ti consigliamo vivamente di implementare un timestamp del token nel codice e nei server e di aggiornarlo a intervalli regolari.
  • Mantenere aggiornati i token e rimuovere quelli obsoleti. Oltre a rimuovere i token che FCM non considera più validi, ti consigliamo di monitorare altri segnali di obsolescenza dei token e di rimuoverli in modo proattivo. Questa guida illustra alcune delle opzioni a tua disposizione per raggiungere questo obiettivo.

Recuperare e archiviare i token di registrazione

All'avvio iniziale dell'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 mirato dall'API o aggiungere agli abbonamenti agli argomenti per il targeting degli argomenti.

Ti consigliamo vivamente di recuperare questo token all'avvio iniziale e di salvarlo nel server dell'app insieme a un timestamp. Questo timestamp deve essere implementato dal tuo codice e dai tuoi server, in quanto non viene fornito dagli SDK 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 torna attiva dopo la scadenza del token esistente di FCM

Esempio: memorizza token e timestamp in Cloud Firestore

Ad esempio, potresti utilizzare Cloud Firestore per archiviare i token in una raccolta chiamata fcmTokens. Ogni ID documento nella raccolta corrisponde a un ID utente e il documento memorizza il token di registrazione corrente e il relativo timestamp dell'ultimo aggiornamento. Utilizza la funzione set come mostrato in questo esempio 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 viene recuperato un token, questo viene memorizzato 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()
            }
        }

Mantenere aggiornati i token e rimuovere quelli obsoleti

Determinare se un token è recente o obsoleto non è sempre semplice. Per coprire tutti i casi, devi adottare una soglia per quando consideri i token obsoleti. Per impostazione predefinita, FCM considera un token obsoleto se la sua istanza dell'app non si connette da un mese. È probabile che un token più vecchio di un mese appartenga a un dispositivo inattivo, altrimenti il token sarebbe stato aggiornato.

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

Rileva risposte di token non valide dal backend FCM

Assicurati di rilevare le risposte con token non validi da FCM e di rispondere 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 richiesta di invio ha preso di mira token non validi o scaduti:

  • 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 un token di destinazione, puoi eliminare in sicurezza il record di questo token, poiché non sarà mai più valido. Ad esempio, per eliminare i token non validi da Cloud Firestore, puoi eseguire il deployment 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 con token non valido solo se un token è scaduto dopo 270 giorni o se un client è stato annullato esplicitamente. Se devi monitorare con maggiore precisione l'obsolescenza in base alle tue definizioni, puoi rimuovere in modo proattivo i token di registrazione obsoleti.

Aggiornare regolarmente i token

Ti consigliamo di recuperare e aggiornare periodicamente tutti i token di registrazione sul tuo server. Per questo devi:

  • Aggiungi 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), quindi invia il token corrente al server dell'app per l'archiviazione (con un timestamp). Potrebbe trattarsi di un job mensile configurato per coprire tutti i clienti o i 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 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 rappresenta un buon equilibrio tra l'impatto sulla batteria e il rilevamento dei token di registrazione inattivi. In questo modo, ti assicuri anche che qualsiasi dispositivo che diventa inattivo aggiorni la registrazione quando torna attivo. Non è utile eseguire l'aggiornamento più di una volta alla settimana.

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 obsolescenza. Ad esempio, puoi implementare Cloud Functions for Firebase per eseguire un controllo giornaliero per assicurarti che il timestamp rientri in un periodo di obsolescenza definito, ad esempio const EXPIRATION_TIME = 1000 * 60 * 60 * 24 * 30;, e poi 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(); });
});

Annullare l'iscrizione ai token obsoleti dagli argomenti

Se utilizzi gli argomenti, ti consigliamo anche di annullare la registrazione dei token obsoleti dagli argomenti a cui sono iscritti. che prevede due passaggi:

  1. L'app deve abbonarsi di nuovo agli argomenti una volta al mese e ogni volta che il token di registrazione cambia. In questo modo si crea una soluzione di auto-ripristino, in cui gli abbonamenti vengono visualizzati di nuovo automaticamente quando un'app torna attiva.
  2. Se un'istanza dell'app è inattiva per un mese (o per il periodo di inattività che hai impostato), devi annullare la sua iscrizione agli argomenti utilizzando l'SDK Firebase Admin per eliminare la mappatura token-argomento dal backend FCM.

Il vantaggio di questi due passaggi è che i fanout verranno eseguiti più rapidamente poiché ci sono meno token obsoleti a cui inviare i fanout e le istanze dell'app obsolete si abboneranno di nuovo automaticamente una volta riattivate.

Misurare la riuscita della pubblicazione

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

Prima di indirizzare i messaggi a un token, considera quanto segue:

  • Google Analytics, i dati acquisiti in BigQuery o altri indicatori di monitoraggio indicano che il token è attivo?
  • I precedenti tentativi di consegna non sono andati a buon fine 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 una percentuale elevata di errori di recapito dei messaggi dovuti a droppedDeviceInactive?

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