FCM रजिस्ट्रेशन मैनेज करने के सबसे सही तरीके

अगर आपने प्रोग्राम के हिसाब से अनुरोध भेजने के लिए FCM एपीआई का इस्तेमाल किया है, तो आपको यह पता चल सकता है कि समय के साथ-साथ, आपने उन डिवाइसों को मैसेज भेजकर संसाधनों को बर्बाद किया है जो अब इस्तेमाल में नहीं हैं. ऐसा इसलिए हुआ, क्योंकि आपने उन डिवाइसों के लिए पुराने रजिस्ट्रेशन का इस्तेमाल किया. इस वजह से, Firebase कंसोल में रिपोर्ट किए गए मैसेज डिलीवरी के डेटा या BigQuery में एक्सपोर्ट किए गए डेटा पर असर पड़ सकता है. इससे डिलीवरी रेट में अचानक गिरावट दिख सकती है, जबकि असल में ऐसा नहीं होता है. इस गाइड में, कुछ ऐसे तरीकों के बारे में बताया गया है जिनसे मैसेज को सही लोगों तक पहुंचाने और डिलीवरी की मान्य रिपोर्टिंग को पक्का करने में मदद मिलती है.

ऐसे रजिस्ट्रेशन जिनकी समयसीमा खत्म हो चुकी है और जो अब काम नहीं करते

पुराने रजिस्ट्रेशन, उन इनऐक्टिव डिवाइसों से जुड़े होते हैं जो एक महीने से ज़्यादा समय से FCM से कनेक्ट नहीं हुए हैं. समय बीतने के साथ-साथ, डिवाइस के FCM से फिर से कनेक्ट होने की संभावना कम होती जाती है. इन पुराने रजिस्ट्रेशन के लिए, मैसेज भेजने और विषय से जुड़े मैसेज पाने की सुविधा कभी भी उपलब्ध नहीं कराई जाएगी.

रजिस्ट्रेशन के पुराने होने की कई वजहें हो सकती हैं. उदाहरण के लिए, जिस डिवाइस से रजिस्ट्रेशन किया गया है वह खो सकता है, खराब हो सकता है या उसे स्टोरेज में रखा जा सकता है और फिर उसे भूल जाया जा सकता है.

Android के लिए, अगर कोई रजिस्ट्रेशन 270 दिनों तक चालू नहीं रहता है, तो FCM उसे एक्सपायर हो चुका मान लेता है और उसे मिटा देता है. रजिस्ट्रेशन की समयसीमा खत्म होने के बाद, FCM इसे अमान्य के तौर पर मार्क करता है और इस पर भेजे गए ईमेल अस्वीकार कर देता है. ध्यान दें कि Firebase इंस्टॉलेशन आईडी (एफआईडी) को Firebase Installations सेवा (एफआईएस) मैनेज करती है, न कि FCM. अगर कोई डिवाइस फिर से कनेक्ट होता है और ऐप्लिकेशन को रजिस्टर करने के बाद, उसे फिर से खोला जाता है, तो क्लाइंट ऐप्लिकेशन, FCM के साथ फिर से रजिस्टर होता है. इसके लिए, वह FIS से मिले FID का इस्तेमाल करता है. ध्यान दें कि एफआईडी बदल सकता है; एफआईडी फिर से कब जारी किए जाते हैं, इस बारे में जानने के लिए Firebase इंस्टॉलेशन मैनेज करें लेख पढ़ें.

iOS जैसे अन्य प्लैटफ़ॉर्म के लिए, FCM, पुश सेवा (जैसे कि APNs) पर निर्भर करता है. इसमें 270 दिनों तक ऐप्लिकेशन इस्तेमाल न करने पर, सदस्यता रद्द होने की सुविधा उपलब्ध नहीं है. हमारा सुझाव है कि आप रजिस्ट्रेशन की जानकारी को समय-समय पर अपडेट करते रहें और पुराने रजिस्ट्रेशन हटा दें.

सबसे सही तरीके

FCM एपीआई का इस्तेमाल करके, प्रोग्राम के हिसाब से अनुरोध भेजने वाले किसी भी ऐप्लिकेशन में, आपको कुछ बुनियादी तरीकों का पालन करना चाहिए. सबसे सही तरीके ये हैं:

  • FCM से Firebase इंस्टॉलेशन आईडी (एफ़आईडी) पाएं और उन्हें अपने ऐप्लिकेशन सर्वर पर सेव करें. सर्वर की एक अहम भूमिका यह है कि वह हर क्लाइंट के रजिस्टर किए गए FID को ट्रैक करे और चालू FID की अपडेट की गई सूची को बनाए रखे. हमारा सुझाव है कि आप अपने डेटाबेस में रजिस्ट्रेशन का टाइमस्टैंप लागू करें. साथ ही, जब भी कोई रजिस्ट्रेशन अपलोड किया जाए, तब इसे अपडेट करें.
  • रजिस्ट्रेशन को अप-टू-डेट रखना और पुराने रजिस्ट्रेशन हटाना. ऐसे रजिस्ट्रेशन हटाने के अलावा जिन्हें FCM अब मान्य नहीं माना जाता, आपको ऐसे अन्य संकेतों पर भी नज़र रखनी चाहिए जिनसे पता चलता है कि रजिस्ट्रेशन पुराने हो गए हैं. साथ ही, उन्हें पहले से ही हटा देना चाहिए. इस गाइड में, ऐसा करने के लिए आपके पास मौजूद कुछ विकल्पों के बारे में बताया गया है.

Firebase इंस्टॉलेशन आईडी को वापस पाना और सेव करना

आपके ऐप्लिकेशन के पहली बार शुरू होने पर, FCM SDK टूल, ऐप्लिकेशन इंस्टेंस को FCM के साथ रजिस्टर करता है. साथ ही, Firebase इंस्टॉलेशन आईडी (FID) दिखाता है. यह वह आइडेंटिफ़ायर है जिसे आपको एपीआई से टारगेट करके भेजे जाने वाले अनुरोधों में शामिल करना होगा. इसके अलावा, इसका इस्तेमाल विषय की सदस्यता के लिए भी किया जा सकता है.

हमारा सुझाव है कि जब भी FID अपलोड किया जाए, तब उसे अपने ऐप्लिकेशन सर्वर पर टाइमस्टैंप के साथ सेव करें. हर अपलोड अनुरोध पर टाइमस्टैंप अपडेट करने से, आपके सर्वर को यह पता चलता है कि ऐप्लिकेशन इंस्टेंस को पिछली बार कब खोला गया था और FCM बैकएंड के साथ कब सिंक किया गया था.

अपने-आप शुरू होने की सुविधा चालू है या बंद है (इसमें सुविधा काम न करने की स्थिति भी शामिल है), इसके आधार पर आपको रजिस्ट्रेशन और अपडेट को इस तरह मैनेज करना चाहिए:

  • (सुझाया गया) जब अपने-आप शुरू होने की सुविधा चालू हो: एसडीके, रजिस्ट्रेशन को अपने-आप अपडेट करता रहता है और बदलावों पर नज़र रखता है. ऐप्लिकेशन शुरू होने के दौरान, रूटीन सिंक पर onRegistered() कॉलबैक को नियमित तौर पर शुरू किया जाता है. साथ ही, ऐसा तब भी होता है, जब FID में बदलाव होते हैं. अपने सर्वर पर FID अपलोड करने और मौजूदा टाइमस्टैंप को सेव करने के लिए, इस कॉलबैक को लागू करें.
  • अपने-आप शुरू होने की सुविधा बंद होने पर: onRegistered() कॉलबैक, शुरू होने पर अपने-आप ट्रिगर नहीं होगा. रजिस्ट्रेशन को ट्रैक करने और उन्हें अपडेट रखने के लिए, ऐप्लिकेशन शुरू होने पर register() को कॉल करें. उदाहरण के लिए, Android पर, मुख्य ऐक्टिविटी के onCreate() में. कॉल पूरा होने पर, FCM रजिस्ट्रेशन की प्रोसेस शुरू हो जाती है. इसमें FID का इस्तेमाल किया जाता है और इसे आपके onRegistered() कॉलबैक को डिलीवर किया जाता है. इससे आपका ऐप्लिकेशन, FID को अपलोड कर पाता है और आपके सर्वर पर टाइमस्टैंप को अपडेट कर पाता है.

उदाहरण: Cloud Firestore में स्टोर के आईडी और टाइमस्टैंप सेव करना

उदाहरण के लिए, Cloud Firestore का इस्तेमाल करके, fcmRegistrations नाम के कलेक्शन में FID सेव किए जा सकते हैं. संग्रह में मौजूद हर दस्तावेज़ आईडी, उपयोगकर्ता आईडी से जुड़ा होता है. साथ ही, दस्तावेज़ में मौजूदा FID और उसके अपडेट होने का टाइमस्टैंप सेव होता है. set फ़ंक्शन का इस्तेमाल करें. यहां 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)
}

जब भी Firebase इंस्टॉलेशन आईडी रजिस्टर या अपडेट हो जाता है, तब onRegistered() कॉलबैक शुरू हो जाता है. आपको इस कॉलबैक को लागू करना चाहिए, ताकि FID को अपलोड किया जा सके और टाइमस्टैंप को अपडेट किया जा सके:

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

अगर अपने-आप शुरू होने की सुविधा बंद है, तो ऐप्लिकेशन शुरू होने पर register() को कॉल करें.उदाहरण के लिए, onCreate() में. इससे रजिस्ट्रेशन फ़्लो और onRegistered() के ज़रिए FID डिलीवरी ट्रिगर हो जाएगी:

// 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 अमान्य जवाब देता है. अगर आपको अपनी परिभाषाओं के हिसाब से, डेटा के अपडेट न होने की स्थिति को ज़्यादा सटीक तरीके से ट्रैक करना है, तो अपडेट न किए गए रजिस्ट्रेशन हटाएं.

नियमित तौर पर रजिस्ट्रेशन अपडेट करना

आपके रजिस्ट्रेशन, FID या लेगसी रजिस्ट्रेशन टोकन पर आधारित हैं या नहीं, इससे कोई फ़र्क़ नहीं पड़ता. आपका सर्वर, अपलोड करने के हर अनुरोध पर आपके डेटाबेस में रजिस्ट्रेशन का टाइमस्टैंप हमेशा अपडेट करता रहना चाहिए. यह टाइमस्टैंप, ऐप्लिकेशन इंस्टॉल करने के लिए एक सिग्नल के तौर पर काम करता है. इससे क्लाइंट को पता चलता है कि ऐप्लिकेशन को सफलतापूर्वक खोल दिया गया है और FCM के बैकएंड के साथ सिंक कर दिया गया है. इस्तेमाल किए जा रहे एपीआई के हिसाब से, सही रणनीति लागू करें:

FID एपीआई का इस्तेमाल करने वाले क्लाइंट ऐप्लिकेशन के लिए, आपको रजिस्ट्रेशन वापस पाने या रीफ़्रेश करने के लिए, अपने क्लाइंट ऐप्लिकेशन में समय-समय पर बैकग्राउंड जॉब शेड्यूल करने की ज़रूरत नहीं है. एसडीके, अपने-आप शुरू होने की सुविधा के तहत रीफ़्रेश का ध्यान रखता है. साथ ही, ऐप्लिकेशन शुरू होने के दौरान नियमित रूप से सिंक होने पर, आपके onRegistered() कॉलबैक को सही मौजूदा FID डिलीवर करता है.

अपने सर्वर को अपडेट रखने के लिए, स्टार्टअप अपलोड करने की उन रणनीतियों को लागू करें जिनके बारे में Firebase इंस्टॉलेशन आईडी वापस पाना और उन्हें सेव करना लेख में बताया गया है:

  • अपने-आप शुरू होने की सुविधा चालू है: एसडीके यह अपने-आप पक्का करता है कि ऐप्लिकेशन शुरू होने के दौरान, रूटीन सिंक पर आपके सर्वर को नया FID भेजा जाए.
  • ऑटो-इनिशियलाइज़ेशन की सुविधा बंद है या मौजूद नहीं है: ऐप्लिकेशन के चालू होने पर, register() को कॉल करें. उदाहरण के लिए, Android पर, मुख्य ऐक्टिविटी के onCreate() में. इससे रजिस्ट्रेशन सीक्वेंस को फ़ोर्स किया जा सकेगा और आपके onRegistered() कॉलबैक को FID डिलीवर किया जा सकेगा.

इन रणनीतियों से यह पक्का होता है कि आपके सर्वर पर हमेशा FID का सबसे नया वर्शन उपलब्ध हो. साथ ही, ये रणनीतियां अपलोड नहीं हो पाने की समस्या को अपने-आप ठीक कर सकती हैं. इससे ऐप्लिकेशन को बेहतर तरीके से काम करने में मदद मिलती है.

रजिस्ट्रेशन टोकन के लिए बंद किए गए एपीआई

लेगसी रजिस्ट्रेशन टोकन का इस्तेमाल करने पर, क्लाइंट एसडीके नियमित सिंक पर रीफ़्रेश को अपने-आप मैनेज नहीं करता है. इसलिए, हमारा सुझाव है कि आप समय-समय पर अपने सर्वर पर सभी रजिस्ट्रेशन टोकन वापस पाएं और उन्हें अपडेट करें. इसके लिए, आपको ये काम करने होंगे:

  • अपने क्लाइंट ऐप्लिकेशन में ऐप्लिकेशन लॉजिक जोड़ें, ताकि सही एपीआई कॉल (जैसे कि Apple प्लैटफ़ॉर्म के लिए token(completion): या Android के लिए getToken()) का इस्तेमाल करके मौजूदा टोकन को वापस पाया जा सके. इसके बाद, मौजूदा टोकन को अपने ऐप्लिकेशन सर्वर पर भेजें, ताकि उसे सेव किया जा सके. साथ ही, टाइमस्टैंप भी सेव किया जा सके. यह हर महीने चलने वाला ऐसा जॉब हो सकता है जिसे सभी क्लाइंट या टोकन के लिए कॉन्फ़िगर किया गया हो.
  • टोकन के टाइमस्टैंप को नियमित अंतराल पर अपडेट करने के लिए, सर्वर लॉजिक जोड़ें. इससे कोई फ़र्क़ नहीं पड़ता कि टोकन बदला है या नहीं.

WorkManager का इस्तेमाल करके लेगसी टोकन अपडेट करने के लिए, Android लॉजिक का उदाहरण देखने के लिए, Firebase ब्लॉग पर Cloud Messaging टोकन मैनेज करना लेख पढ़ें.

आप जिस भी समय के पैटर्न का इस्तेमाल करें, यह पक्का करें कि टोकन को समय-समय पर अपडेट किया जाए. महीने में एक बार अपडेट करने से, बैटरी पर पड़ने वाले असर और इनऐक्टिव रजिस्ट्रेशन टोकन का पता लगाने के बीच सही संतुलन बना रहता है. इस तरह रीफ़्रेश करने से, यह भी पक्का किया जा सकेगा कि बंद पड़ा कोई डिवाइस फिर से चालू होने पर, अपना रजिस्ट्रेशन रीफ़्रेश कर ले. डेटा को हफ़्ते में एक बार से ज़्यादा बार रीफ़्रेश करने से कोई फ़ायदा नहीं होता.

पुराने रजिस्ट्रेशन हटाना

किसी डिवाइस को मैसेज भेजने से पहले, पक्का करें कि डिवाइस के रजिस्ट्रेशन का टाइमस्टैंप, स्टेलनेस विंडो की अवधि के अंदर हो. उदाहरण के लिए, 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(); });
});
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(); }); });

विषयों से पुरानी सदस्यताएं छोड़ना

अगर विषयों का इस्तेमाल किया जाता है, तो आपको उन विषयों से पुराने रजिस्ट्रेशन की सदस्यता भी छोड़नी पड़ सकती है जिनकी उन्होंने सदस्यता ली है. इसके लिए, ये दो चरण पूरे करें:

  1. जब भी Firebase इंस्टॉलेशन आईडी (एफ़आईडी) बदलता है, तब आपके ऐप्लिकेशन को विषयों की सदस्यता फिर से लेनी चाहिए. इससे किसी ऐप्लिकेशन के फिर से चालू होने पर, सदस्यताएं अपने-आप दिखने लगती हैं.
  2. अगर कोई ऐप्लिकेशन इंस्टेंस एक महीने तक (या आपकी तय की गई अवधि तक) इस्तेमाल नहीं किया जाता है, तो आपको उसे विषयों से सदस्यता रद्द करनी चाहिए. इसके लिए, Firebase Admin SDK का इस्तेमाल करें. इससे FCM बैकएंड से, Firebase इंस्टॉलेशन आईडी को विषय से मैप करने की सुविधा मिट जाएगी.

इन दो चरणों का फ़ायदा यह है कि आपके फ़ैनआउट तेज़ी से होंगे, क्योंकि फ़ैन आउट करने के लिए कम पुरानी जानकारी वाले रजिस्ट्रेशन हैं. साथ ही, आपके पुरानी जानकारी वाले ऐप्लिकेशन इंस्टेंस, फिर से ऐक्टिव होने पर अपने-आप फिर से सदस्यता ले लेंगे.

डिलीवरी की सफलता को मेज़र करना

मैसेज डिलीवर होने की सबसे सटीक जानकारी पाने के लिए, सिर्फ़ उन ऐप्लिकेशन इंस्टेंस को मैसेज भेजें जिनका इस्तेमाल किया जा रहा है. यह खास तौर पर तब ज़रूरी होता है, जब आपको ऐसे विषयों पर नियमित रूप से मैसेज भेजने हों जिनके लिए बड़ी संख्या में लोगों ने सदस्यता ली हो. अगर इनमें से कुछ सदस्य असल में निष्क्रिय हैं, तो समय के साथ-साथ मैसेज डिलीवर होने से जुड़े आंकड़ों पर इसका काफ़ी असर पड़ सकता है.

किसी ऐप्लिकेशन इंस्टेंस को मैसेज टारगेट करने से पहले, इन बातों का ध्यान रखें:

  • क्या Google Analytics, BigQuery में कैप्चर किया गया डेटा या अन्य ट्रैकिंग सिग्नल से पता चलता है कि रजिस्ट्रेशन चालू है?
  • क्या डिलीवरी करने की पिछली कोशिशें, तय समय में लगातार फ़ेल हुई हैं?
  • क्या पिछले महीने आपके सर्वर पर Firebase इंस्टॉलेशन आईडी अपडेट किया गया था?
  • क्या Android डिवाइसों के लिए, FCM Data API, droppedDeviceInactive की वजह से मैसेज डिलीवर न होने की ज़्यादा दर दिखाता है?

डिलीवरी के बारे में ज़्यादा जानने के लिए, मैसेज की डिलीवरी के बारे में जानकारी लेख पढ़ें.