Si vous utilisez les API FCM pour créer des requêtes d'envoi de manière programmatique, vous constaterez peut-être qu'au fil du temps, vous gaspillez des ressources en envoyant des messages à des appareils inactifs dont les enregistrements sont obsolètes. Cette situation peut affecter les données de distribution des messages indiquées dans la console Firebase ou les données exportées vers BigQuery, qui se traduisent par une baisse spectaculaire (mais pas réellement valide) des taux de distribution. Ce guide présente certaines mesures que vous pouvez prendre pour garantir un ciblage efficace des messages et des rapports de distribution valides.
Enregistrements obsolètes et expirés
Les enregistrements obsolètes sont associés à des appareils inactifs qui ne se sont pas connectés à FCM depuis plus d'un mois. Plus le temps passe, moins il est probable que l'appareil se reconnecte à FCM. Les envois de messages et les fanouts de thèmes pour ces enregistrements obsolètes ne seront probablement jamais distribués.
Plusieurs raisons peuvent expliquer qu'un enregistrement devienne obsolète. Par exemple, l'appareil auquel l'enregistrement est associé peut être perdu, détruit ou stocké et oublié.
Sur Android, lorsqu'un enregistrement est inactif depuis 270 jours, FCM le considère comme expiré et le récupère. Une fois l'enregistrement arrivé à expiration, FCM le marque comme non valide et refuse les envois vers celui-ci. Notez que les ID d'installation Firebase (FID) sont gérés par le service d'installation Firebase (FIS), et non par FCM. Dans les rares cas où un appareil se reconnecte et où l'application est ouverte après que son enregistrement a été récupéré par le garbage collector, l'application cliente s'enregistre à nouveau auprès de FCM à l'aide du FID récupéré à partir de FIS. Notez que le FID peut changer. Consultez Gérer les installations Firebase pour savoir quand les FID sont réémis.
Pour les autres plates-formes comme iOS, FCM s'appuie sur le service push sous-jacent (par exemple, APNs), qui n'a pas la même expiration basée sur l'inactivité de 270 jours. Nous vous recommandons de maintenir de manière proactive l'actualisation des enregistrements et de supprimer les enregistrements obsolètes.
Bonnes pratiques de base
Il existe des pratiques fondamentales que vous devez suivre dans toute application qui utilise les API FCM pour créer des requêtes d'envoi de manière programmatique. Voici les principales bonnes pratiques :
- Récupérez les ID d'installation Firebase (FID) à partir de FCM et stockez-les sur votre serveur d'application. Le serveur joue un rôle important, car il doit suivre le FID enregistré de chaque client et tenir à jour la liste des FID actifs. Nous vous recommandons vivement d'implémenter un code temporel d'enregistrement dans votre base de données et de le mettre à jour chaque fois qu'un enregistrement est importé.
- Maintenez l'actualisation des enregistrements et supprimez les enregistrements obsolètes. En plus de supprimer les enregistrements que FCM ne considère plus comme valides, vous pouvez surveiller d'autres signes indiquant que les enregistrements sont devenus obsolètes et les supprimer de manière proactive. Ce guide présente quelques-unes des options disponibles pour y parvenir.
Récupérer et stocker les ID d'installation Firebase
Lors du démarrage initial de votre application, le SDK FCM enregistre l'instance de l'application auprès de FCM et renvoie un ID d'installation Firebase (FID). Il s'agit de l'identifiant que vous devez inclure dans les requêtes d'envoi ciblées de l'API ou utiliser pour les abonnements à des thèmes.
Nous vous recommandons vivement d'enregistrer le FID sur votre serveur d'application, ainsi qu'un code temporel, chaque fois qu'il est importé. En mettant à jour le code temporel à chaque requête d'importation, votre serveur sait quand l'instance de l'application a été ouverte pour la dernière fois et synchronisée avec le backend FCM.
Selon que l'initialisation automatique est activée ou désactivée (y compris si elle n'est pas prise en charge), vous devez gérer l'enregistrement et les mises à jour comme suit :
- (Recommandé) Lorsque l'initialisation automatique est activée : le SDK actualise automatiquement l'enregistrement et surveille les modifications. Le rappel
onRegistered()est appelé régulièrement lors des synchronisations de routine au démarrage de l'application, ainsi que lorsque des modifications du FID se produisent. Il vous suffit d'implémenter ce rappel pour importer le FID sur votre serveur et enregistrer le code temporel actuel. - Lorsque l'initialisation automatique est désactivée : le rappel
onRegistered()n'est pas appelé automatiquement au démarrage. Pour suivre les enregistrements et les actualiser, appelezregister()au démarrage de l'application (par exemple, sur Android, dans l'activité principaleonCreate()). Un appel réussi déclenche le processus d'enregistrement FCM à l'aide du FID et le transmet à votre rappelonRegistered(), ce qui permet à votre application d'importer le FID et de mettre à jour le code temporel sur votre serveur.
Exemple : Stocker les FID et les codes temporels dans Cloud Firestore
Par exemple, vous pouvez utiliser Cloud Firestore pour stocker les FID dans une collection appelée fcmRegistrations. Chaque ID de document de la collection correspond à un ID utilisateur, et le document stocke le FID actuel et son code temporel de dernière mise à jour. Utilisez la fonction set, comme illustré dans cet exemple 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)
}
Chaque fois qu'un ID d'installation Firebase est enregistré ou mis à jour, le rappel onRegistered() est appelé. Vous devez implémenter ce rappel pour importer le FID et mettre à jour le code temporel :
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)
}
Si l'initialisation automatique est désactivée, appelez register() au démarrage de l'application (par exemple, dans onCreate()) pour déclencher le flux d'enregistrement et la diffusion du FID via 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)
}
}
Maintenir l'actualisation des enregistrements et supprimer les enregistrements obsolètes
Il n'est pas toujours facile de déterminer si un enregistrement est récent ou obsolète. Pour couvrir tous les cas, vous devez adopter un seuil à partir duquel vous considérez les enregistrements comme obsolètes. Par défaut, FCM considère qu'un enregistrement est obsolète si son instance d'application ne s'est pas connectée depuis un mois. Tout enregistrement datant de plus d'un mois est susceptible d'être un appareil inactif. Un appareil actif aurait actualisé son enregistrement.
Selon votre cas d'utilisation, un mois peut être trop court ou trop long. C'est donc à vous de déterminer les critères qui vous conviennent.
Détecter les réponses non valides du backend FCM
Veillez à détecter les réponses non valides de FCM et à supprimer de votre système toutes les inscriptions connues comme non valides ou ayant expiré. Avec l'API HTTP v1, ces messages d'erreur peuvent indiquer que votre demande d'envoi ciblait des enregistrements 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 enregistrement ciblé, vous pouvez supprimer l'enregistrement de cette inscription, car il ne sera plus jamais valide. Par exemple, pour supprimer les enregistrements non valides de Cloud Firestore, vous pouvez déployer et exécuter une fonction comme celle-ci :
// 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 renvoie une réponse non valide si l'enregistrement d'un appareil Android a expiré après 270 jours d'inactivité ou si un client s'est explicitement désinscrit. Si vous devez suivre l'obsolescence de manière plus précise en fonction de vos propres définitions, vous pouvez supprimer de manière proactive les enregistrements obsolètes.
Mettre à jour régulièrement les enregistrements
Que vos enregistrements soient basés sur des FID ou d'anciens jetons d'enregistrement, votre serveur doit toujours mettre à jour le code temporel d'enregistrement dans votre base de données à chaque demande d'importation. Ce code temporel sert de signal pour l'installation de l'application, ce qui permet au client d'ouvrir l'application et de la synchroniser avec le backend FCM. Selon les API que vous utilisez, implémentez la stratégie appropriée :
Les API d'ID d'installation Firebase (recommandé)
Pour les applications clientes utilisant les API FID, vous n'avez pas besoin de planifier des tâches périodiques en arrière-plan dans votre application cliente pour récupérer ou actualiser les enregistrements. Le SDK gère automatiquement les actualisations lors de l'initialisation automatique, en envoyant régulièrement le FID actuel correct à votre rappel onRegistered() lors des synchronisations de routine au démarrage de l'application.
Pour maintenir votre serveur à jour, implémentez les stratégies d'importation au démarrage décrites dans Récupérer et stocker les ID d'installation Firebase :
- Initialisation automatique activée : le SDK s'assure automatiquement que le dernier FID est envoyé à votre serveur lors des synchronisations de routine au démarrage de l'application.
- L'initialisation automatique est désactivée ou non compatible : appelez
register()au démarrage de l'application (par exemple, sur Android, dans l'activité principaleonCreate()) pour forcer la séquence d'enregistrement et déclencher l'envoi du FID à votre rappelonRegistered().
Ces stratégies garantissent que votre serveur dispose toujours du dernier FID actif et qu'il peut récupérer automatiquement après l'échec d'une importation, ce qui rend l'application hautement résiliente.
API de jeton d'enregistrement obsolètes
Si vous utilisez d'anciens jetons d'enregistrement, le SDK client ne gère pas automatiquement les actualisations lors des synchronisations de routine. Par conséquent, nous vous recommandons de récupérer et de mettre à jour régulièrement tous les jetons d'enregistrement sur votre serveur. Pour ce faire, 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 ougetToken()pour Android), puis envoyez le jeton actuel à votre serveur d'application pour le stocker (avec un code temporel). Il peut s'agir d'un job mensuel configuré pour couvrir tous les clients ou jetons. - Ajoutez une logique de serveur pour mettre à jour le code temporel du jeton à intervalles réguliers, que le jeton ait changé ou non.
Pour obtenir un exemple de logique Android permettant de mettre à jour les anciens jetons à l'aide de WorkManager, consultez Gérer les jetons Cloud Messaging sur le blog Firebase.
Quel que soit le modèle de timing que vous suivez, veillez à mettre à jour les jetons régulièrement. Une fréquence de mise à jour d'une fois par mois offre un bon équilibre entre l'impact sur la batterie et la détection des jetons d'enregistrement inactifs. En effectuant cette actualisation, vous vous assurez également que tout appareil qui devient inactif actualisera son enregistrement lorsqu'il redeviendra actif. Il n'est pas utile d'effectuer l'actualisation plus d'une fois par semaine.
Supprimer les enregistrements obsolètes
Avant d'envoyer des messages à un appareil, assurez-vous que l'horodatage de l'enregistrement de l'appareil se situe dans la période de votre fenêtre d'obsolescence. Par exemple, vous pouvez implémenter Cloud Functions for Firebase pour exécuter une vérification quotidienne afin de vous assurer que le code temporel se trouve dans une période d'obsolescence définie, telle que const
EXPIRATION_TIME = 1000 * 60 * 60 * 24 * 30;, puis supprimer les enregistrements obsolètes :
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(); });
});
Désabonner les enregistrements obsolètes des thèmes
Si vous utilisez des thèmes, vous pouvez également désabonner les enregistrements obsolètes des thèmes auxquels ils sont abonnés. Cela implique deux étapes :
- Votre application doit se réabonner aux thèmes chaque fois que l'ID d'installation Firebase (FID) change. Cela permet aux abonnements de réapparaître automatiquement lorsqu'une application redevient active.
- Si une instance d'application est inactive pendant un mois (ou votre propre période d'obsolescence), vous devez la désabonner des thèmes à l'aide du SDK Admin Firebase pour supprimer l'ID d'installation Firebase du mappage de thèmes du backend FCM.
L'avantage de ces deux étapes est que vos fanouts se produiront plus rapidement, car il y a moins d'enregistrements obsolètes vers lesquels effectuer un fanout, et vos instances d'application obsolètes se réabonneront automatiquement une fois qu'elles seront de nouveau actives.
Mesurer la réussite des livraisons
Pour obtenir l'image la plus précise possible de la distribution des messages, il est préférable de n'envoyer des messages qu'aux instances d'application utilisées activement. Cela est particulièrement important si vous envoyez régulièrement des messages à des thèmes comptant un grand nombre d'abonnés. Si une partie de ces abonnés est inactive, l'impact sur vos statistiques de distribution peut être significatif au fil du temps.
Avant de cibler des messages vers une instance d'application, tenez compte des points suivants :
- Google Analytics, les données capturées dans BigQuery ou d'autres signaux de suivi indiquent-ils que l'inscription est active ?
- Les tentatives de livraison précédentes ont-elles échoué de manière répétée sur une certaine période ?
- L'ID d'installation Firebase a-t-il été mis à jour sur vos serveurs au cours du mois dernier ?
- Pour les appareils Android, l'API de données FCM signale-t-elle un pourcentage élevé d'échecs de distribution des messages en raison de
droppedDeviceInactive?
Pour en savoir plus sur la distribution, consultez Comprendre la distribution des messages.