अगर प्रोग्राम के हिसाब से अनुरोध भेजने के लिए FCM एपीआई का इस्तेमाल किया जाता है, तो आपको पता चल सकता है कि समय के साथ, पुराने रजिस्ट्रेशन वाले बंद डिवाइसों पर मैसेज भेजकर, संसाधनों को बर्बाद किया जा रहा है. इस स्थिति का असर, Firebase कंसोल में रिपोर्ट किए गए मैसेज डिलीवरी के डेटा या BigQuery में एक्सपोर्ट किए गए डेटा पर पड़ सकता है. इससे डिलीवरी रेट में काफ़ी गिरावट दिख सकती है. हालांकि, असल में ऐसा नहीं होता है. इस गाइड में कुछ ऐसे तरीकों के बारे में बताया गया है जिनकी मदद से, मैसेज को सही ऑडियंस तक पहुंचाया जा सकता है और डिलीवरी की मान्य रिपोर्टिंग की जा सकती है.
पुराने और समयसीमा खत्म हो चुके रजिस्ट्रेशन
पुराने रजिस्ट्रेशन, उन डिवाइसों से जुड़े होते हैं जो एक महीने से ज़्यादा समय से FCM से कनेक्ट नहीं हुए हैं. समय बीतने के साथ, डिवाइस के FCM से फिर से कनेक्ट होने की संभावना कम होती जाती है. इन पुराने रजिस्ट्रेशन के लिए, मैसेज भेजने और विषय के फ़ैनआउट डिलीवर होने की संभावना नहीं है.
रजिस्ट्रेशन के पुराना होने की कई वजहें हो सकती हैं. उदाहरण के लिए, हो सकता है कि रजिस्ट्रेशन से जुड़ा डिवाइस खो गया हो, नष्ट हो गया हो या उसे स्टोरेज में रखकर भूल गए हों.
Android के लिए, जब कोई रजिस्ट्रेशन 270 दिनों तक इनऐक्टिव रहता है, तो FCM उसे समयसीमा खत्म हो चुकी मान लेता है और उसे मिटा देता है. रजिस्ट्रेशन की समयसीमा खत्म होने के बाद, FCM उसे अमान्य के तौर पर मार्क कर देता है और उस पर मैसेज भेजने की अनुमति नहीं देता. ध्यान दें कि Firebase इंस्टॉलेशन आईडी (FID), Firebase इंस्टॉलेशन सेवा (एफ़आईएस) से मैनेज किए जाते हैं, न कि एफ़सीएम से. कभी-कभी ऐसा हो सकता है कि डिवाइस फिर से कनेक्ट हो जाए और रजिस्ट्रेशन के गार्बेज कलेक्शन के बाद ऐप्लिकेशन खोला जाए. ऐसे में, क्लाइंट ऐप्लिकेशन, एफ़आईएस से मिले एफ़आईडी का इस्तेमाल करके, FCM के साथ फिर से रजिस्टर करता है. ध्यान दें कि एफ़आईडी में बदलाव हो सकता है. एफ़आईडी को फिर से जारी करने के बारे में ज़्यादा जानने के लिए, Firebase इंस्टॉलेशन मैनेज करना लेख पढ़ें.
iOS जैसे अन्य प्लैटफ़ॉर्म के लिए, FCM पुश सेवा (जैसे, APNs) पर निर्भर करता है. इस सेवा में, 270 दिनों तक इस्तेमाल न होने पर टोकन की समयसीमा खत्म होने की शर्त लागू नहीं होती. हमारा सुझाव है कि आप रजिस्ट्रेशन को अप-टू-डेट रखें और पुराने रजिस्ट्रेशन हटाएं.
सबसे सही तरीके
प्रोग्राम के हिसाब से अनुरोध भेजने के लिए, FCM एपीआई का इस्तेमाल करने वाले किसी भी ऐप्लिकेशन में आपको कुछ बुनियादी तरीकों का पालन करना चाहिए. सबसे सही तरीके ये हैं:
- FCM से Firebase इंस्टॉलेशन आईडी (FID) वापस पाएं और उन्हें अपने ऐप्लिकेशन सर्वर पर सेव करें. सर्वर का एक अहम काम, हर क्लाइंट के रजिस्टर किए गए एफ़आईडी को ट्रैक करना और चालू एफ़आईडी की अपडेट की गई सूची को बनाए रखना है. हमारा सुझाव है कि आप अपने डेटाबेस में रजिस्ट्रेशन का टाइमस्टैंप लागू करें. साथ ही, रजिस्ट्रेशन अपलोड होने पर उसे अपडेट करें.
- रजिस्ट्रेशन को अप-टू-डेट रखें और पुराने रजिस्ट्रेशन हटाएं. FCM जिन रजिस्ट्रेशन को अब मान्य नहीं मानता उन्हें हटाने के अलावा, आपको उन अन्य संकेतों पर भी नज़र रखनी चाहिए जिनसे पता चलता है कि रजिस्ट्रेशन पुराने हो गए हैं. साथ ही, उन्हें पहले से ही हटा देना चाहिए. इस गाइड में, ऐसा करने के लिए कुछ विकल्पों के बारे में बताया गया है.
Firebase इंस्टॉलेशन आईडी को वापस पाना और उन्हें सेव करना
ऐप्लिकेशन को पहली बार शुरू करने पर, FCM SDK टूल, ऐप्लिकेशन इंस्टेंस को FCM के साथ रजिस्टर करता है. साथ ही, Firebase इंस्टॉलेशन आईडी (FID) दिखाता है. यह वह आइडेंटिफ़ायर है जिसे आपको एपीआई से टारगेट किए गए मैसेज भेजने के अनुरोधों में शामिल करना होगा या विषय की सदस्यताओं के लिए इस्तेमाल करना होगा.
हमारा सुझाव है कि जब भी एफ़आईडी अपलोड किया जाए, तो उसे टाइमस्टैंप के साथ अपने ऐप्लिकेशन सर्वर पर सेव करें. अपलोड करने के हर अनुरोध पर टाइमस्टैंप अपडेट करने से, आपके सर्वर को पता चलता है कि ऐप्लिकेशन इंस्टेंस को पिछली बार कब खोला गया था और FCM बैकएंड के साथ कब सिंक किया गया था.
अपने-आप शुरू होने की सुविधा चालू या बंद होने (इसमें सुविधा का काम न करना भी शामिल है) के आधार पर, आपको रजिस्ट्रेशन और अपडेट को इस तरह मैनेज करना चाहिए:
- (सुझाया गया) अपने-आप शुरू होने की सुविधा चालू होने पर: एसडीके, रजिस्ट्रेशन को अपने-आप अपडेट रखता है और बदलावों पर नज़र रखता है.
onRegistered()कॉलबैक को ऐप्लिकेशन के स्टार्टअप के दौरान रूटीन सिंक पर नियमित रूप से शुरू किया जाता है. साथ ही, एफ़आईडी में बदलाव होने पर भी इसे शुरू किया जाता है. अपने सर्वर पर एफ़आईडी अपलोड करने और मौजूदा टाइमस्टैंप को सेव करने के लिए, बस इस कॉलबैक को लागू करें. - अपने-आप शुरू होने की सुविधा बंद होने पर: शुरुआत में,
onRegistered()कॉलबैक अपने-आप शुरू नहीं होगा. रजिस्ट्रेशन को ट्रैक करने और उन्हें अप-टू-डेट रखने के लिए, ऐप्लिकेशन के स्टार्टअप परregister()को कॉल करें. उदाहरण के लिए, Android पर मुख्य गतिविधि केonCreate()में. कॉल पूरा होने पर, एफ़आईडी का इस्तेमाल करके FCM रजिस्ट्रेशन की प्रोसेस ट्रिगर होती है. साथ ही, इसे आपकेonRegistered()कॉलबैक पर डिलीवर किया जाता है. इससे आपका ऐप्लिकेशन, एफ़आईडी अपलोड कर पाता है और आपके सर्वर पर टाइमस्टैंप को अपडेट कर पाता है.
उदाहरण: Cloud Firestore में एफ़आईडी और टाइमस्टैंप सेव करना
उदाहरण के लिए, Cloud Firestore का इस्तेमाल करके, एफ़आईडी को fcmRegistrations नाम के कलेक्शन में सेव किया जा सकता है. कलेक्शन में मौजूद हर दस्तावेज़ आईडी, किसी यूज़र आईडी से जुड़ा होता है. साथ ही, दस्तावेज़ में मौजूदा एफ़आईडी और उसके पिछली बार अपडेट किए गए टाइमस्टैंप को सेव किया जाता है. Kotlin के इस उदाहरण में दिखाए गए तरीके से, set फ़ंक्शन का इस्तेमाल करें:
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)
}
जब भी कोई Firebase इंस्टॉलेशन आईडी रजिस्टर या अपडेट किया जाता है, तो onRegistered() कॉलबैक को शुरू किया जाता है. आपको एफ़आईडी अपलोड करने और टाइमस्टैंप को अपडेट करने के लिए, इस कॉलबैक को लागू करना चाहिए:
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)
}
अगर अपने-आप शुरू होने की सुविधा बंद है, तो ऐप्लिकेशन के स्टार्टअप पर (उदाहरण के लिए, onCreate() में) register() को कॉल करें, ताकि रजिस्ट्रेशन फ़्लो और एफ़आईडी डिलीवरी को 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)
}
}
रजिस्ट्रेशन को अप-टू-डेट रखना और पुराने रजिस्ट्रेशन हटाना
यह तय करना हमेशा आसान नहीं होता कि रजिस्ट्रेशन नया है या पुराना. सभी मामलों को कवर करने के लिए, आपको एक थ्रेशोल्ड तय करना चाहिए. इससे आपको यह तय करने में मदद मिलेगी कि रजिस्ट्रेशन कब पुराने हो गए हैं. डिफ़ॉल्ट रूप से, FCM किसी रजिस्ट्रेशन को तब पुराना मानता है, जब उसका ऐप्लिकेशन इंस्टेंस एक महीने से कनेक्ट न हुआ हो. एक महीने से ज़्यादा पुराना रजिस्ट्रेशन, आम तौर पर किसी ऐसे डिवाइस का होता है जो इस्तेमाल में नहीं है. अगर डिवाइस इस्तेमाल में होता, तो उसका रजिस्ट्रेशन रीफ़्रेश हो जाता.
आपके इस्तेमाल के उदाहरण के आधार पर, एक महीना बहुत कम या बहुत ज़्यादा हो सकता है. इसलिए, यह आप पर निर्भर करता है कि आपके लिए कौनसी शर्त सही है.
FCM बैकएंड से मिले अमान्य जवाबों का पता लगाना
FCM से मिले गलत जवाबों का पता लगाएं. साथ ही, अपने सिस्टम से ऐसे सभी रजिस्ट्रेशन मिटाएं जो अमान्य हैं या जिनकी समयसीमा खत्म हो चुकी है. एचटीटीपी v1 एपीआई का इस्तेमाल करने पर, गड़बड़ी के ये मैसेज दिख सकते हैं. इनसे पता चलता है कि आपके भेजे गए अनुरोध में, अमान्य या समयसीमा खत्म हो चुके रजिस्ट्रेशन को टारगेट किया गया है:
UNREGISTERED(एचटीटीपी 404)INVALID_ARGUMENT(एचटीटीपी 400)
अगर आपको पक्का पता है कि मैसेज पेलोड मान्य है और आपको टारगेट किए गए रजिस्ट्रेशन के लिए इनमें से कोई भी जवाब मिलता है, तो इस रजिस्ट्रेशन का रिकॉर्ड मिटाना सुरक्षित है. ऐसा इसलिए, क्योंकि यह फिर कभी मान्य नहीं होगा. उदाहरण के लिए, Cloud Firestore से अमान्य रजिस्ट्रेशन मिटाने के लिए, इस तरह का फ़ंक्शन डिप्लॉय करके चलाया जा सकता है:
// 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()
}
});
अगर किसी Android डिवाइस के लिए रजिस्ट्रेशन, 270 दिनों तक इस्तेमाल न होने की वजह से खत्म हो गया है या किसी क्लाइंट ने साफ़ तौर पर रजिस्ट्रेशन रद्द कर दिया है, तो FCM गलत जवाब दिखाता है. अगर आपको अपनी परिभाषाओं के हिसाब से, पुराने रजिस्ट्रेशन को ज़्यादा सटीक तरीके से ट्रैक करना है, तो पुराने रजिस्ट्रेशन को हटाया जा सकता है.
रजिस्ट्रेशन को समय-समय पर अपडेट करना
चाहे आपके रजिस्ट्रेशन, एफ़आईडी पर आधारित हों या लेगसी रजिस्ट्रेशन टोकन पर, आपके सर्वर को हर अपलोड अनुरोध पर, आपके डेटाबेस में रजिस्ट्रेशन का टाइमस्टैंप हमेशा अपडेट करना चाहिए. यह टाइमस्टैंप, ऐप्लिकेशन इंस्टॉल करने के लिए एक सिग्नल के तौर पर काम करता है. इससे क्लाइंट को ऐप्लिकेशन खोलने और FCM बैकएंड के साथ सिंक करने में मदद मिलती है. इस्तेमाल किए जा रहे एपीआई के हिसाब से, सही रणनीति लागू करें:
Firebase इंस्टॉलेशन आईडी एपीआई (सुझाया गया)
FID एपीआई का इस्तेमाल करने वाले क्लाइंट ऐप्लिकेशन के लिए, आपको क्लाइंट ऐप्लिकेशन में समय-समय पर बैकग्राउंड में होने वाले जॉब शेड्यूल करने की ज़रूरत नहीं है. ऐसा रजिस्ट्रेशन को वापस पाने या रीफ़्रेश करने के लिए किया जाता है. एसडीके, अपने-आप शुरू होने की सुविधा के तहत रीफ़्रेश होने की प्रोसेस को अपने-आप मैनेज करता है. साथ ही, ऐप्लिकेशन के स्टार्टअप के दौरान रूटीन सिंक पर आपके onRegistered() कॉलबैक को नियमित तौर पर सही मौजूदा एफ़आईडी डिलीवर करता है.
अपने सर्वर को अपडेट रखने के लिए, स्टार्टअप अपलोड की रणनीतियां लागू करें. इनके बारे में, Firebase इंस्टॉलेशन आईडी को वापस पाना और उन्हें स्टोर करना लेख में बताया गया है:
- अपने-आप शुरू होने की सुविधा चालू है: SDK टूल यह पक्का करता है कि ऐप्लिकेशन शुरू होने के दौरान, रूटीन सिंक पर आपके सर्वर को नया एफ़आईडी अपने-आप भेजा जाए.
- अपने-आप शुरू होने की सुविधा बंद है या काम नहीं करती: ऐप्लिकेशन के स्टार्टअप पर (उदाहरण के लिए, Android पर, मुख्य गतिविधि के
onCreate()में)register()को कॉल करें, ताकि रजिस्ट्रेशन के क्रम को लागू किया जा सके और आपकेonRegistered()कॉलबैक पर एफ़आईडी डिलीवरी को ट्रिगर किया जा सके.
इन रणनीतियों से यह पक्का होता है कि आपके सर्वर के पास हमेशा सबसे नया चालू एफ़आईडी हो. साथ ही, अपलोड न हो पाने की समस्या अपने-आप ठीक हो जाए. इससे ऐप्लिकेशन को बेहतर तरीके से काम करने में मदद मिलती है.
रजिस्ट्रेशन टोकन के लिए इस्तेमाल किए जाने वाले पुराने एपीआई
अगर लेगसी रजिस्ट्रेशन टोकन का इस्तेमाल किया जा रहा है, तो क्लाइंट एसडीके, रूटीन सिंक पर रीफ़्रेश को अपने-आप मैनेज नहीं करता. इसलिए, हमारा सुझाव है कि आप समय-समय पर अपने सर्वर पर सभी रजिस्ट्रेशन टोकन वापस पाएं और उन्हें अपडेट करें. इसके लिए, आपको ये काम करने होंगे:
- अपने क्लाइंट ऐप्लिकेशन में ऐप्लिकेशन लॉजिक जोड़ें, ताकि सही एपीआई कॉल का इस्तेमाल करके मौजूदा टोकन को वापस लाया जा सके. जैसे, Apple प्लैटफ़ॉर्म के लिए
token(completion):या Android के लिएgetToken(). इसके बाद, मौजूदा टोकन को अपने ऐप्लिकेशन सर्वर पर भेजें, ताकि उसे टाइमस्टैंप के साथ सेव किया जा सके. यह हर महीने होने वाला ऐसा काम हो सकता है जिसे सभी क्लाइंट या टोकन को कवर करने के लिए कॉन्फ़िगर किया गया हो. - टोकन के टाइमस्टैंप को नियमित अंतराल पर अपडेट करने के लिए, सर्वर लॉजिक जोड़ें. इससे कोई फ़र्क़ नहीं पड़ता कि टोकन बदला है या नहीं.
WorkManager का इस्तेमाल करके, लेगसी टोकन अपडेट करने के लिए Android लॉजिक का उदाहरण देखने के लिए, Firebase ब्लॉग पर क्लाउड से मैसेज के टोकन मैनेज करना देखें.
चाहे आप किसी भी टाइमिंग पैटर्न का इस्तेमाल करें, टोकन को समय-समय पर अपडेट करना न भूलें. महीने में एक बार अपडेट का अंतराल रखने से, बैटरी पर पड़ने वाले असर और इनऐक्टिव रजिस्ट्रेशन टोकन का पता लगाने के बीच अच्छा संतुलन बनता है. इस तरह से रीफ़्रेश करने पर, यह भी पक्का किया जाता है कि बंद हो चुका कोई भी डिवाइस, फिर से चालू होने पर अपना रजिस्ट्रेशन रीफ़्रेश करेगा. हफ़्ते में एक बार से ज़्यादा रीफ़्रेश करने का कोई फ़ायदा नहीं है.
पुराने रजिस्ट्रेशन हटाना
किसी डिवाइस पर मैसेज भेजने से पहले, पक्का करें कि डिवाइस के रजिस्ट्रेशन का टाइमस्टैंप, आपके तय किए गए समय के अंदर हो. उदाहरण के लिए, Cloud Functions for Firebase को लागू करके हर दिन यह जांच की जा सकती है कि टाइमस्टैंप, तय की गई समयसीमा के अंदर है या नहीं. जैसे, const
EXPIRATION_TIME = 1000 * 60 * 60 * 24 * 30;. इसके बाद, पुराने रजिस्ट्रेशन हटाए जा सकते हैं:
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(); });
});
विषयों से पुराने रजिस्ट्रेशन की सदस्यता छोड़ना
अगर विषयों का इस्तेमाल किया जाता है, तो हो सकता है कि आप उन विषयों से पुराने रजिस्ट्रेशन की सदस्यता भी छोड़ना चाहें जिनकी सदस्यता ली गई है. इसके लिए, आपको ये दो काम करने होंगे:
- जब भी Firebase इंस्टॉलेशन आईडी (FID) बदले, तब आपके ऐप्लिकेशन को विषयों की सदस्यता फिर से लेनी चाहिए. इससे, ऐप्लिकेशन के फिर से चालू होने पर, सदस्यताएं अपने-आप दिखने लगती हैं.
- अगर कोई ऐप्लिकेशन इंस्टेंस एक महीने (या आपके तय किए गए समय) तक इस्तेमाल नहीं किया जाता है, तो आपको Firebase Admin SDK का इस्तेमाल करके, उसे विषयों से अनसब्सक्राइब कर देना चाहिए. इससे FCM बैकएंड से, विषय की मैपिंग के लिए Firebase इंस्टॉलेशन आईडी मिटाया जा सकेगा.
इन दो चरणों का फ़ायदा यह है कि आपके फ़ैनआउट तेज़ी से होंगे, क्योंकि फ़ैनआउट करने के लिए पुराने रजिस्ट्रेशन कम होंगे. साथ ही, आपके पुराने ऐप्लिकेशन इंस्टेंस फिर से चालू होने पर, अपने-आप फिर से सदस्यता ले लेंगे.
डिलीवरी की सफलता को मेज़र करना
मैसेज डिलीवरी की सबसे सटीक जानकारी पाने के लिए, सिर्फ़ उन ऐप्लिकेशन इंस्टेंस पर मैसेज भेजें जो ऐक्टिव हैं. यह खास तौर पर तब ज़रूरी है, जब आप नियमित तौर पर ऐसे विषयों पर मैसेज भेजते हैं जिनके सदस्यों की संख्या ज़्यादा है. अगर उन सदस्यों में से कुछ सदस्य असल में इनऐक्टिव हैं, तो समय के साथ आपके डिलीवरी के आंकड़ों पर काफ़ी असर पड़ सकता है.
किसी ऐप्लिकेशन इंस्टेंस को मैसेज टारगेट करने से पहले, इन बातों का ध्यान रखें:
- क्या Google Analytics, BigQuery में कैप्चर किया गया डेटा या अन्य ट्रैकिंग सिग्नल से पता चलता है कि रजिस्ट्रेशन चालू है?
- क्या पिछले कुछ समय से, डिलीवरी की कोशिशें लगातार नाकाम हो रही हैं?
- क्या पिछले महीने आपके सर्वर पर Firebase इंस्टॉलेशन आईडी अपडेट किया गया है?
- क्या Android डिवाइसों के लिए, FCM डेटा एपीआई,
droppedDeviceInactiveकी वजह से मैसेज डिलीवर न होने की ज़्यादा दर की रिपोर्ट करता है?
मैसेज की डिलीवरी के बारे में ज़्यादा जानने के लिए, मैसेज की डिलीवरी को समझना लेख पढ़ें.