Flutter ऐप्लिकेशन में मैसेज पाएं

डिवाइस की स्थिति के हिसाब से, आने वाले मैसेज अलग-अलग तरीके से मैनेज किए जाते हैं. इन स्थितियों को समझने और FCM को अपने ऐप्लिकेशन में इंटिग्रेट करने का तरीका जानने के लिए, सबसे पहले यह तय करना ज़रूरी है कि डिवाइस की अलग-अलग स्थितियां क्या हो सकती हैं:

राज्य जानकारी
फ़ोरग्राउंड जब ऐप्लिकेशन खुला हो, तब व्यू में और इस्तेमाल में हो.
बैकग्राउंड जब ऐप्लिकेशन खुला हो, लेकिन बैकग्राउंड में (कम से कम). ऐसा आम तौर पर तब होता है, जब उपयोगकर्ता ने डिवाइस पर "होम" बटन दबाया हो, ऐप्लिकेशन स्विचर का इस्तेमाल करके किसी दूसरे ऐप्लिकेशन पर स्विच किया हो या ऐप्लिकेशन को किसी दूसरे टैब (वेब) में खोला हो.
शर्तों को खत्म किया गया जब डिवाइस लॉक हो या ऐप्लिकेशन नहीं चल रहा हो.

ऐप्लिकेशन को FCM के ज़रिए मैसेज पेलोड मिल सके, इससे पहले कुछ शर्तों को पूरा करना ज़रूरी है:

  • (FCM के साथ पंजीकरण की अनुमति देने के लिए) कम से कम एक बार ऐप्लिकेशन खोला जाना चाहिए.
  • iOS पर, अगर उपयोगकर्ता ऐप स्विचर से ऐप्लिकेशन को स्वाइप करके हटा देता है, तो बैकग्राउंड में मैसेज फिर से काम कर सकें, इसके लिए ऐप्लिकेशन को मैन्युअल रूप से फिर से खोलना होगा.
  • Android पर, अगर उपयोगकर्ता डिवाइस की सेटिंग में जाकर ऐप्लिकेशन को ज़बरदस्ती बंद करता है, तो मैसेज को मैन्युअल तरीके से फिर से खोला जाना चाहिए, ताकि मैसेज काम करना शुरू कर सकें.
  • वेब पर, आपने वेब पुश सर्टिफ़िकेट के साथ टोकन (getToken() का इस्तेमाल करके) का अनुरोध किया होगा.

मैसेज पाने के लिए अनुमति का अनुरोध करें

iOS, macOS, वेब, और Android 13 (या इसके बाद के वर्शन) पर, अपने डिवाइस पर FCM पेलोड पाने से पहले, आपको उपयोगकर्ता की अनुमति लेनी होगी.

requestPermission तरीके से अनुमति का अनुरोध करने के लिए, firebase_messaging पैकेज एक आसान एपीआई उपलब्ध कराता है. यह एपीआई कई नाम वाले आर्ग्युमेंट स्वीकार करता है, जो तय करते हैं कि आपको किस तरह की अनुमतियों के लिए अनुरोध करना है. जैसे- क्या सूचना पेलोड वाली मैसेज सेवा, Siri के ज़रिए आवाज़ ट्रिगर कर सकती है या मैसेज पढ़ सकती है. डिफ़ॉल्ट रूप से, यह तरीका समझने लायक डिफ़ॉल्ट अनुमतियों का अनुरोध करता है. रेफ़रंस एपीआई, हर अनुमति के बारे में पूरे दस्तावेज़ उपलब्ध कराता है.

शुरू करने के लिए, अपने ऐप्लिकेशन से मेथड को कॉल करें (iOS पर एक नेटिव मॉडल दिखाया जाएगा, वेब पर ब्राउज़र का नेटिव एपीआई फ़्लो ट्रिगर हो जाएगा):

FirebaseMessaging messaging = FirebaseMessaging.instance;

NotificationSettings settings = await messaging.requestPermission(
  alert: true,
  announcement: false,
  badge: true,
  carPlay: false,
  criticalAlert: false,
  provisional: false,
  sound: true,
);

print('User granted permission: ${settings.authorizationStatus}');

अनुरोध करने पर मिले NotificationSettings ऑब्जेक्ट की authorizationStatus प्रॉपर्टी का इस्तेमाल करके, उपयोगकर्ता के फ़ैसले का पता लगाया जा सकता है:

  • authorized: उपयोगकर्ता ने अनुमति दी है.
  • denied: उपयोगकर्ता ने अनुमति नहीं दी.
  • notDetermined: उपयोगकर्ता ने अभी तक यह नहीं चुना है कि अनुमति देनी है या नहीं.
  • provisional: उपयोगकर्ता ने अस्थायी तौर पर अनुमति दी है

NotificationSettings की अन्य प्रॉपर्टी से पता चलता है कि मौजूदा डिवाइस पर कोई खास अनुमति चालू है, बंद है या काम नहीं करती.

अनुमति देने और डिवाइस की अलग-अलग तरह की स्थिति समझने के बाद, आपका ऐप्लिकेशन अब इनकमिंग FCM पेलोड को मैनेज करना शुरू कर सकता है.

मैसेज मैनेज करना

आपके ऐप्लिकेशन की मौजूदा स्थिति के आधार पर, अलग-अलग मैसेज टाइप के आने वाले पेलोड को मैनेज करने के लिए, उन्हें अलग-अलग तरह से लागू करने की ज़रूरत होती है:

फ़ोरग्राउंड मैसेज

ऐप्लिकेशन के फ़ोरग्राउंड में होने पर मैसेज मैनेज करने के लिए, onMessage स्ट्रीम सुनें.

FirebaseMessaging.onMessage.listen((RemoteMessage message) {
  print('Got a message whilst in the foreground!');
  print('Message data: ${message.data}');

  if (message.notification != null) {
    print('Message also contained a notification: ${message.notification}');
  }
});

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

फ़ोरग्राउंड और सूचना वाले मैसेज

ऐप्लिकेशन के फ़ोरग्राउंड में होने पर आने वाले सूचना मैसेज, Android और iOS, दोनों पर डिफ़ॉल्ट रूप से कोई सूचना नहीं दिखाएंगे. हालांकि, इस व्यवहार को बदला जा सकता है:

  • Android पर, आपको "ज़्यादा प्राथमिकता" का सूचना चैनल बनाना होगा.
  • iOS पर, आप ऐप्लिकेशन के प्रज़ेंटेशन विकल्पों को अपडेट कर सकते हैं.

बैकग्राउंड मैसेज

बैकग्राउंड में मैसेज मैनेज करने की प्रोसेस, नेटिव (Android और Apple) और वेब पर आधारित प्लैटफ़ॉर्म पर अलग-अलग होती है.

Apple प्लैटफ़ॉर्म और Android

onBackgroundMessage हैंडलर रजिस्टर करके बैकग्राउंड के मैसेज मैनेज करें. जब मैसेज मिलते हैं, तो एक आइसोलेट दिखता है. यह सुविधा सिर्फ़ Android पर, iOS/macOS के लिए अलग से आइसोलेट नहीं होती. इसकी मदद से, ऐप्लिकेशन के बंद होने पर भी मैसेज मैनेज किए जा सकते हैं.

बैकग्राउंड मैसेज हैंडलर के बारे में कुछ बातों का ध्यान रखना ज़रूरी है:

  1. यह बिना नाम वाला फ़ंक्शन नहीं होना चाहिए.
  2. यह एक टॉप लेवल फ़ंक्शन होना चाहिए. उदाहरण के लिए, यह कोई ऐसा क्लास तरीका नहीं है जिसके लिए इनिशलाइज़ेशन ज़रूरी हो.
  3. Flutter के 3.3.0 या इसके बाद वाले वर्शन का इस्तेमाल करते समय, मैसेज हैंडलर को फ़ंक्शन एलान के ठीक ऊपर @pragma('vm:entry-point') के साथ एनोटेट किया जाना चाहिए. ऐसा न करने पर, रिलीज़ मोड के दौरान ट्री शेकिंग के दौरान इसे हटाया जा सकता है.
@pragma('vm:entry-point')
Future<void> _firebaseMessagingBackgroundHandler(RemoteMessage message) async {
  // If you're going to use other Firebase services in the background, such as Firestore,
  // make sure you call `initializeApp` before using other Firebase services.
  await Firebase.initializeApp();

  print("Handling a background message: ${message.messageId}");
}

void main() {
  FirebaseMessaging.onBackgroundMessage(_firebaseMessagingBackgroundHandler);
  runApp(MyApp());
}

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

हमारा सुझाव है कि जितनी जल्दी हो सके अपने लॉजिक को पूरा करें. लंबे समय तक ज़्यादा मेहनत करने वाले टास्क, डिवाइस की परफ़ॉर्मेंस पर असर डालते हैं. इसकी वजह से ओएस इस प्रोसेस को बंद कर सकता है. अगर टास्क 30 सेकंड से ज़्यादा समय तक चलते हैं, तो हो सकता है कि डिवाइस इस प्रोसेस को अपने-आप खत्म कर दे.

वेब

वेब पर, बैकग्राउंड में चलने वाला JavaScript Service Worker लिखें. बैकग्राउंड मैसेज मैनेज करने के लिए सर्विस वर्कर का इस्तेमाल करें.

शुरू करने के लिए, अपनी web डायरेक्ट्री में एक नई फ़ाइल बनाएं और उसे firebase-messaging-sw.js नाम दें:

importScripts("https://www.gstatic.com/firebasejs/8.10.0/firebase-app.js");
importScripts("https://www.gstatic.com/firebasejs/8.10.0/firebase-messaging.js");

firebase.initializeApp({
  apiKey: "...",
  authDomain: "...",
  databaseURL: "...",
  projectId: "...",
  storageBucket: "...",
  messagingSenderId: "...",
  appId: "...",
});

const messaging = firebase.messaging();

// Optional:
messaging.onBackgroundMessage((message) => {
  console.log("onBackgroundMessage", message);
});

इस फ़ाइल में, ऐप्लिकेशन और मैसेजिंग SDK टूल, दोनों को इंपोर्ट करना होगा. साथ ही, Firebase को शुरू करना होगा और messaging वैरिएबल को दिखाना होगा.

इसके बाद, वर्कर का रजिस्ट्रेशन होना ज़रूरी है. एंट्री फ़ाइल में, main.dart.js फ़ाइल लोड होने के बाद, अपना वर्कर रजिस्टर करें:

<html>
<body>
  ...
  <script src="main.dart.js" type="application/javascript"></script>
  <script>
       if ('serviceWorker' in navigator) {
          // Service workers are supported. Use them.
          window.addEventListener('load', function () {
            // ADD THIS LINE
            navigator.serviceWorker.register('/firebase-messaging-sw.js');

            // Wait for registration to finish before dropping the <script> tag.
            // Otherwise, the browser will load the script multiple times,
            // potentially different versions.
            var serviceWorkerUrl = 'flutter_service_worker.js?v=' + serviceWorkerVersion;

            //  ...
          });
      }
  </script>

अब अपने Flutter ऐप्लिकेशन को रीस्टार्ट करें. वर्कर को रजिस्टर किया जाएगा और बैकग्राउंड मैसेज को इस फ़ाइल से मैनेज किया जाएगा.

इंटरैक्शन मैनेज करना

सूचनाएं साफ़ तौर पर दिखती हैं, इसलिए उपयोगकर्ताओं के लिए उनसे इंटरैक्ट करना (दबाकर) सामान्य बात है. Android और iOS, दोनों पर डिफ़ॉल्ट रूप से ऐप्लिकेशन खोलना होता है. अगर ऐप्लिकेशन खत्म हो जाता है, तो उसे शुरू कर दिया जाएगा. अगर ऐप्लिकेशन बैकग्राउंड में है, तो उसे फ़ोरग्राउंड में लाया जाएगा.

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

firebase-messaging पैकेज में इस इंटरैक्शन को मैनेज करने के दो तरीके मौजूद हैं:

  • getInitialMessage(): अगर ऐप्लिकेशन को बंद स्थिति से खोला जाता है, तो RemoteMessage वाला Future लौटाया जाएगा. इस्तेमाल करने पर, RemoteMessage को हटा दिया जाएगा.
  • onMessageOpenedApp: एक Stream, जो बैकग्राउंड में ऐप्लिकेशन खोले जाने पर, RemoteMessage पोस्ट करता है.

हमारा सुझाव है कि दोनों मामलों को इस तरह मैनेज करें कि उपयोगकर्ताओं को बेहतर अनुभव मिले. नीचे दिए गए उदाहरण में बताया गया है कि इसे कैसे हासिल किया जा सकता है:

class Application extends StatefulWidget {
  @override
  State<StatefulWidget> createState() => _Application();
}

class _Application extends State<Application> {
  // It is assumed that all messages contain a data field with the key 'type'
  Future<void> setupInteractedMessage() async {
    // Get any messages which caused the application to open from
    // a terminated state.
    RemoteMessage? initialMessage =
        await FirebaseMessaging.instance.getInitialMessage();

    // If the message also contains a data property with a "type" of "chat",
    // navigate to a chat screen
    if (initialMessage != null) {
      _handleMessage(initialMessage);
    }

    // Also handle any interaction when the app is in the background via a
    // Stream listener
    FirebaseMessaging.onMessageOpenedApp.listen(_handleMessage);
  }

  void _handleMessage(RemoteMessage message) {
    if (message.data['type'] == 'chat') {
      Navigator.pushNamed(context, '/chat',
        arguments: ChatArguments(message),
      );
    }
  }

  @override
  void initState() {
    super.initState();

    // Run code required to handle interacted messages in an async function
    // as initState() must not be async
    setupInteractedMessage();
  }

  @override
  Widget build(BuildContext context) {
    return Text("...");
  }
}

ऐप्लिकेशन के सेटअप के आधार पर यह तय होता है कि इंटरैक्शन को कैसे मैनेज किया जाएगा. ऊपर दिया गया उदाहरण, StatefulWidget का इस्तेमाल करके बुनियादी इलस्ट्रेशन दिखाता है.

मैसेज को स्थानीय भाषा में उपलब्ध कराएं

स्थानीय जगह के मुताबिक स्ट्रिंग को दो अलग-अलग तरीकों से भेजा जा सकता है:

  • अपने सर्वर में अपने हर उपयोगकर्ता की पसंदीदा भाषा को सेव करें और हर भाषा के लिए पसंद के मुताबिक सूचनाएं भेजें
  • अपने ऐप्लिकेशन में स्थानीय जगह के अनुसार स्ट्रिंग एम्बेड करें और ऑपरेटिंग सिस्टम की स्थानीय भाषा सेटिंग का इस्तेमाल करें

यहां दूसरे तरीके के इस्तेमाल का तरीका बताया गया है:

Android

  1. resources/values/strings.xml में अपनी डिफ़ॉल्ट भाषा के मैसेज बताएं:

    <string name="notification_title">Hello world</string>
    <string name="notification_message">This is a message</string>
    
  2. values-language डायरेक्ट्री में, अनुवाद किए गए मैसेज के बारे में बताएं. उदाहरण के लिए, resources/values-fr/strings.xml में फ़्रेंच मैसेज तय करें:

    <string name="notification_title">Bonjour le monde</string>
    <string name="notification_message">C'est un message</string>
    
  3. सर्वर पेलोड में, title, message, और body कुंजियों का इस्तेमाल करने के बजाय, स्थानीय भाषा में लिखे गए मैसेज के लिए title_loc_key और body_loc_key का इस्तेमाल करें. साथ ही, उन्हें उस मैसेज की name एट्रिब्यूट पर सेट करें जिसे आपको दिखाना है.

    मैसेज पेलोड कुछ ऐसा दिखेगा:

    {
      "data": {
        "title_loc_key": "notification_title",
        "body_loc_key": "notification_message"
      }
    }
    

iOS

  1. Base.lproj/Localizable.strings में अपनी डिफ़ॉल्ट भाषा के मैसेज बताएं:

    "NOTIFICATION_TITLE" = "Hello World";
    "NOTIFICATION_MESSAGE" = "This is a message";
    
  2. language.lproj डायरेक्ट्री में, अनुवाद किए गए मैसेज के बारे में बताएं. उदाहरण के लिए, fr.lproj/Localizable.strings में फ़्रेंच मैसेज तय करें:

    "NOTIFICATION_TITLE" = "Bonjour le monde";
    "NOTIFICATION_MESSAGE" = "C'est un message";
    

    मैसेज पेलोड कुछ ऐसा दिखेगा:

    {
      "data": {
        "title_loc_key": "NOTIFICATION_TITLE",
        "body_loc_key": "NOTIFICATION_MESSAGE"
      }
    }
    

मैसेज डिलीवरी का डेटा एक्सपोर्ट करने की सुविधा चालू करें

ज़्यादा विश्लेषण के लिए, मैसेज के डेटा को BigQuery में एक्सपोर्ट किया जा सकता है. BigQuery की मदद से, BigQuery एसक्यूएल का इस्तेमाल करके डेटा का विश्लेषण किया जा सकता है, इसे किसी दूसरी क्लाउड सेवा देने वाली कंपनी पर एक्सपोर्ट किया जा सकता है या अपने कस्टम एमएल मॉडल के लिए डेटा का इस्तेमाल किया जा सकता है. BigQuery में एक्सपोर्ट में, मैसेज के लिए उपलब्ध सारा डेटा शामिल होता है. इस बात से कोई फ़र्क़ नहीं पड़ता कि मैसेज किस तरह का है या उसे एपीआई या नोटिफ़िकेशन कंपोज़र से भेजा गया है या नहीं.

एक्सपोर्ट चालू करने के लिए, पहले यहां बताया गया तरीका अपनाएं. इसके बाद, इन निर्देशों का पालन करें:

Android

इस कोड का इस्तेमाल किया जा सकता है:

await FirebaseMessaging.instance.setDeliveryMetricsExportToBigQuery(true);

iOS

iOS के लिए, आपको नीचे दिए गए कॉन्टेंट के साथ AppDelegate.m में बदलाव करना होगा.

#import "AppDelegate.h"
#import "GeneratedPluginRegistrant.h"
#import <Firebase/Firebase.h>

@implementation AppDelegate

- (BOOL)application:(UIApplication *)application
    didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
  [GeneratedPluginRegistrant registerWithRegistry:self];
  // Override point for customization after application launch.
  return [super application:application didFinishLaunchingWithOptions:launchOptions];
}

- (void)application:(UIApplication *)application
    didReceiveRemoteNotification:(NSDictionary *)userInfo
          fetchCompletionHandler:(void (^)(UIBackgroundFetchResult))completionHandler {
  [[FIRMessaging extensionHelper] exportDeliveryMetricsToBigQueryWithMessageInfo:userInfo];
}

@end

वेब

वेब के लिए, आपको SDK टूल के v9 वर्शन का इस्तेमाल करने के लिए, सर्विस वर्कर में बदलाव करना होगा. v9 वर्शन को बंडल करना होगा, इसलिए सर्विस वर्कर को अच्छे से चलाने के लिए आपको esbuild जैसे बंडलर का इस्तेमाल करना होगा. ऐसा करने का तरीका जानने के लिए, उदाहरण के तौर पर दिया गया ऐप्लिकेशन देखें.

v9 SDK टूल पर माइग्रेट करने के बाद, इस कोड का इस्तेमाल किया जा सकता है:

import {
  experimentalSetDeliveryMetricsExportedToBigQueryEnabled,
  getMessaging,
} from 'firebase/messaging/sw';
...

const messaging = getMessaging(app);
experimentalSetDeliveryMetricsExportedToBigQueryEnabled(messaging, true);

अपने सर्विस वर्कर के नए वर्शन को web फ़ोल्डर में एक्सपोर्ट करने के लिए, yarn build चलाना न भूलें.

iOS पर सूचनाओं में इमेज दिखाएं

Apple डिवाइसों पर, इनकमिंग FCM नोटिफ़िकेशन को FCM पेलोड से इमेज दिखाने के लिए, आपको एक अतिरिक्त नोटिफ़िकेशन सेवा एक्सटेंशन जोड़ना होगा और अपने ऐप्लिकेशन का इस्तेमाल करने के लिए उसे कॉन्फ़िगर करना होगा.

अगर Firebase फ़ोन से पुष्टि करने की सुविधा का इस्तेमाल किया जा रहा है, तो आपको Podfile में Firebase पुष्टि पॉड जोड़ना होगा.

पहला चरण - सूचना सेवा एक्सटेंशन जोड़ें

  1. Xcode में, फ़ाइल > नया > टारगेट... पर क्लिक करें
  2. मॉडल, संभावित टारगेट की सूची दिखाएगा. इसके लिए, नीचे स्क्रोल करें या फ़िल्टर का इस्तेमाल करके, सूचना सेवा एक्सटेंशन चुनें. आगे बढ़ें पर क्लिक करें.
  3. प्रॉडक्ट का नाम जोड़ें (इस ट्यूटोरियल के साथ आगे बढ़ने के लिए, "ImageNotification" का इस्तेमाल करें), भाषा को Objective-C पर सेट करें, और पूरा करें पर क्लिक करें.
  4. चालू करें पर क्लिक करके स्कीम को चालू करें.

दूसरा चरण - Podfile में टारगेट जोड़ें

पक्का करें कि आपके नए एक्सटेंशन के पास Firebase/Messaging पॉड को Podfile में जोड़कर उसका ऐक्सेस हो:

  1. Navigator में जाकर, Podfile खोलें: Pods > Podfile

  2. फ़ाइल में नीचे तक स्क्रोल करें और जोड़ें:

    target 'ImageNotification' do
      use_frameworks!
      pod 'Firebase/Auth' # Add this line if you are using FirebaseAuth phone authentication
      pod 'Firebase/Messaging'
    end
    
  3. ios या macos डायरेक्ट्री से pod install का इस्तेमाल करके, अपने पॉड इंस्टॉल या अपडेट करें.

तीसरा चरण - एक्सटेंशन हेल्पर का इस्तेमाल करें

इस दौरान, सब कुछ सामान्य रूप से चल रहा होगा. आखिरी चरण में एक्सटेंशन हेल्पर को शुरू किया जा रहा है.

  1. नेविगेटर से, ImageNotification एक्सटेंशन को चुनें

  2. NotificationService.m फ़ाइल खोलें.

  3. फ़ाइल में सबसे ऊपर, NotificationService.h के ठीक बाद FirebaseMessaging.h को इंपोर्ट करें, जैसा कि नीचे दिखाया गया है.

    NotificationService.m की सामग्री को इससे बदलें:

    #import "NotificationService.h"
    #import "FirebaseMessaging.h"
    #import "FirebaseAuth.h" // Add this line if you are using FirebaseAuth phone authentication
    #import <UIKit/UIKit.h> // Add this line if you are using FirebaseAuth phone authentication
    
    @interface NotificationService ()
    
    @property (nonatomic, strong) void (^contentHandler)(UNNotificationContent *contentToDeliver);
    @property (nonatomic, strong) UNMutableNotificationContent *bestAttemptContent;
    
    @end
    
    @implementation NotificationService
    
    /* Uncomment this if you are using Firebase Auth
    - (BOOL)application:(UIApplication *)app
                openURL:(NSURL *)url
                options:(NSDictionary<UIApplicationOpenURLOptionsKey, id> *)options {
      if ([[FIRAuth auth] canHandleURL:url]) {
        return YES;
      }
      return NO;
    }
    
    - (void)scene:(UIScene *)scene openURLContexts:(NSSet<UIOpenURLContext *> *)URLContexts {
      for (UIOpenURLContext *urlContext in URLContexts) {
        [FIRAuth.auth canHandleURL:urlContext.URL];
      }
    }
    */
    
    - (void)didReceiveNotificationRequest:(UNNotificationRequest *)request withContentHandler:(void (^)(UNNotificationContent * _Nonnull))contentHandler {
        self.contentHandler = contentHandler;
        self.bestAttemptContent = [request.content mutableCopy];
    
        // Modify the notification content here...
        [[FIRMessaging extensionHelper] populateNotificationContent:self.bestAttemptContent withContentHandler:contentHandler];
    }
    
    - (void)serviceExtensionTimeWillExpire {
        // Called just before the extension will be terminated by the system.
        // Use this as an opportunity to deliver your "best attempt" at modified content, otherwise the original push payload will be used.
        self.contentHandler(self.bestAttemptContent);
    }
    
    @end
    

चौथा चरण - पेलोड में इमेज जोड़ें

सूचना पेलोड में, अब इमेज जोड़ी जा सकती है. अनुरोध भेजने का तरीका जानने के लिए iOS दस्तावेज़ देखें. ध्यान रखें कि इमेज का साइज़ 300 केबी से ज़्यादा नहीं होना चाहिए.