Bonnes pratiques de gestion des jetons d'enregistrement FCM

Si vous utilisez les API FCM pour créer des requêtes d'envoi par programmation, vous pouvez : constatez qu'au fil du temps, vous gaspillez des ressources en envoyant des messages à des comptes appareils avec des jetons d'enregistrement obsolètes. Cette situation peut affecter les données de diffusion des messages indiquées dans la console Firebase ou les données exportées vers BigQuery, ce qui se traduit par une baisse importante (mais non valide) des taux de diffusion. Ce présente quelques mesures à prendre pour assurer l'efficacité de vos messages et des rapports de diffusion valides.

Jetons d'enregistrement obsolètes et expirés

Les jetons d'enregistrement obsolètes sont des jetons associés à des appareils inactifs qui ne se sont pas connectés à FCM depuis plus d'un mois. Au fil du temps, il devient de moins en moins probable que l'appareil se reconnecte à FCM. Envoyer un message Il est peu probable que les envois et les distributions de sujet pour ces jetons obsolètes livrés.

Un jeton peut devenir obsolète pour plusieurs raisons. Par exemple, l'appareil auquel le jeton est associé peuvent être perdus, détruits ou mis dans le stockage ou oubliés.

Lorsque les jetons obsolètes atteignent 270 jours d'inactivité, FCM les considère comme des jetons expirés. Une fois qu'un jeton expire, FCM le marque comme non valide et refuse les envois qui lui sont destinés. Cependant, FCM émet un nouveau jeton pour l'application. dans les rares cas où l'appareil se reconnecte et que l'application est ouverte.

Bonnes pratiques de base

Il existe quelques pratiques fondamentales que vous devez suivre dans toute application qui utilise Des API FCM permettant de créer des requêtes d'envoi de manière automatisée Le meilleur pratiques sont:

  • Récupérez les jetons d'enregistrement à partir de FCM et stockez-les sur votre Google Cloud. Un rôle important pour le serveur est de garder une trace des un jeton et conserver une liste à jour des jetons actifs. Nous vous recommandons vivement implémenter un code temporel de jeton dans votre code et vos serveurs, et mettre à jour cet horodatage à intervalles réguliers.
  • Maintenez la fraîcheur des jetons et supprimez les jetons obsolètes. En plus de en supprimant les jetons que FCM ne considère plus comme valides, vous pouvez de surveiller les autres signes indiquant que les jetons sont obsolètes et de les supprimer de manière proactive. Ce guide décrit certaines des options qui s'offrent à vous pour y parvenir.

Récupérer et stocker les jetons d'enregistrement

Au démarrage initial de votre application, le SDK FCM génère un jeton d'enregistrement pour l'instance de l'application cliente. Il s'agit du jeton que vous devez inclure dans des demandes d'envoi ciblées à partir de l'API ou ajouter des abonnés à des thèmes à des fins de ciblage des sujets.

Nous recommandons vivement à votre application de récupérer ce jeton au démarrage initial et d'enregistrer à votre serveur d'applications avec un code temporel. Ce code temporel doit être implémentée par votre code et vos serveurs, car elle n'est pas fournie FCM.

Il est également important d'enregistrer le jeton sur le serveur et de mettre à jour l'horodatage chaque fois qu'elle change, par exemple dans les cas suivants:

  • L'appli est restaurée sur un nouvel appareil
  • L'utilisateur désinstalle ou réinstalle l'application
  • L'utilisateur efface les données de l'application.
  • L'application redevient active lorsque FCM a expiré jeton

Exemple: stocker des jetons et des codes temporels dans Cloud Firestore

Par exemple, vous pouvez utiliser Cloud Firestore pour stocker des jetons dans une collection appelée fcmTokens. Chaque ID de document de la collection correspond à un ID utilisateur, et le document stocke le jeton d'enregistrement actuel et son code temporel de la dernière mise à jour. Utilisez la fonction set comme indiqué dans cet exemple 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)
    }

Chaque fois qu'un jeton est récupéré, il est stocké dans Cloud Firestore en appelant 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()
            }
        }

Maintenir la fraîcheur des jetons et supprimer les jetons obsolètes

Il n'est pas toujours facile de déterminer si un jeton est à jour ou obsolète. À couvrir tous les cas, vous devez adopter un seuil non actualisés. Par défaut, FCM considère qu'un jeton est obsolète si son application ne s'est pas connectée depuis un mois. Tout jeton datant de plus d'un mois être un appareil inactif ; qu'un appareil actif aurait actualisé à partir d'un jeton d'accès.

Selon votre cas d'utilisation, un mois peut être trop court ou trop long, donc il est en hausse. pour déterminer les critères qui vous conviennent le mieux.

Détecter les réponses de jetons non valides du backend FCM

Assurez-vous de détecter les réponses de jeton non valides de FCM et de supprimer de votre système tous les jetons d'enregistrement connus comme non valides ou expirés. Avec l'API HTTP v1, ces messages d'erreur peuvent indiquer que votre demande d'envoi ciblait des jetons non valides ou arrivés à expiration:

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

Si vous êtes certain que la charge utile du message est valide et que vous recevez l'une de ces réponses pour un jeton ciblé, vous pouvez supprimer votre enregistrement de ce jeton, car il ne sera plus jamais valide. Par exemple, pour supprimer les jetons non valides À partir de Cloud Firestore, vous pouvez déployer et exécuter une fonction semblable à celle-ci:

    // 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 ne renverra une réponse de jeton non valide que si le jeton a expiré après 270 jours ou si un client s'est désinscrit explicitement. Si vous devez suivre plus précisément l'obsolescence en fonction de vos propres définitions, vous pouvez supprimer de manière proactive les jetons d'enregistrement obsolètes.

Mettre à jour les jetons régulièrement

Nous vous recommandons de récupérer et de mettre à jour régulièrement tous les jetons d'enregistrement sur votre serveur. Pour cela, vous devez:

  • Ajoutez une logique d'application dans votre application cliente pour récupérer le jeton actuel à l'aide de l'appel d'API approprié (par exemple, token(completion): pour les plates-formes Apple ou getToken() pour Android), puis envoyez le jeton actuel à votre serveur d'application pour le stocker (avec un code temporel). Il peut s'agir d'une tâche mensuelle configurée pour couvrir tous les clients ou jetons.
  • Ajouter une logique de serveur pour mettre à jour l'horodatage du jeton à intervalles réguliers que le jeton ait changé ou non.

Voici un exemple de logique Android pour la mise à jour de jetons à l'aide de WorkManager voir Gérer les jetons Cloud Messaging sur le blog Firebase.

Quel que soit le modèle de synchronisation que vous suivez, assurez-vous de mettre à jour les jetons régulièrement. Une une fréquence de mise à jour mensuelle d'une fois par mois offre un bon équilibre entre l'impact de la batterie et détecter les jetons d'enregistrement inactifs. Cette actualisation vous permet aussi de s'assurer que tout appareil inactif actualisera son enregistrement est réactivé. L'actualisation plus fréquente ne présente aucun avantage. qu'une fois par semaine.

Supprimer les jetons d'enregistrement obsolètes

Avant d'envoyer des messages à un appareil, assurez-vous que l'horodatage des le jeton d'enregistrement n'est pas disponible dans la période d'obsolescence. Par exemple : pourrait implémenter Cloud Functions for Firebase pour exécuter une vérification quotidienne afin de s'assurer que se situe dans une période d'obsolescence définie, telle que const EXPIRATION_TIME = 1000 * 60 * 60 * 24 * 30;, puis supprimez les jetons obsolètes:

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

Se désabonner des jetons obsolètes des thèmes

Si vous utilisez des thèmes, vous pouvez également annuler l'enregistrement des jetons obsolètes pour les thèmes. auxquelles ils sont abonnés. Pour ce faire, procédez comme suit :

  1. Votre application doit se réabonner aux thèmes une fois par mois et chaque fois que les modifications de jetons d'enregistrement. Il s'agit d'une solution d'autoréparation, où les abonnements réapparaissent automatiquement lorsqu'une application redevient active.
  2. Si une instance d'application est inactive pendant un mois (ou pendant votre propre période d'inactivité), vous devez la désabonner des sujets à l'aide du SDK Admin Firebase pour supprimer le mappage du jeton sur le sujet du backend FCM.

L'avantage de ces deux étapes est que vos sortances se produisent plus rapidement, il y a moins de jetons obsolètes vers lesquels effectuer une distribution ramifiée, et vos instances d'application obsolètes se réabonnent automatiquement lorsqu'ils sont de nouveau actifs.

Mesurer la réussite des livraisons

Pour obtenir la représentation la plus précise possible de la distribution d'un message, il est préférable de n'envoyer aux instances d'application activement utilisées. Cela est particulièrement important si vous envoyez régulièrement des messages à des sujets comportant un grand nombre d'abonnés. Si une partie de ces abonnés est inactive, l'impact sur vos statistiques de distribution peut être important au fil du temps.

Avant de cibler des messages sur un jeton, tenez compte des points suivants:

  • Google Analytics, les données capturées dans BigQuery ou d'autres signaux de suivi indique-t-il que le jeton est actif ?
  • Les tentatives d'envoi précédentes ont-elles échoué régulièrement sur une période donnée ?
  • Le jeton d'enregistrement a-t-il été mis à jour sur vos serveurs au cours du mois dernier ?
  • Pour les appareils Android, l'API FCM Data est-elle disponible ? signalent un pourcentage élevé d'échecs de distribution des messages dus à droppedDeviceInactive?

Pour en savoir plus sur la diffusion, consultez Comprendre la distribution des messages