Flutter অ্যাপে মেসেজ পাওয়া

প্ল্যাটফর্ম বেছে নিন: iOS+ Android ওয়েব Flutter Unity C++


ডিভাইসের অবস্থার উপর নির্ভর করে, ইনকামিং মেসেজ আলাদাভাবে ম্যানেজ করা হয়। এইসব পরিস্থিতি এবং কীভাবে আপনার নিজের অ্যাপ্লিকেশনে FCM ইন্টিগ্রেট করবেন তা বোঝার জন্য, প্রথমে ডিভাইস কোন কোন বিভিন্ন স্টেটে থাকতে পারে তা নির্ধারণ করা গুরুত্বপূর্ণ:

রাজ্য বিবরণ
ফোরগ্রাউন্ড অ্যাপ্লিকেশন খোলা, দেখা ও ব্যবহার করা হচ্ছে।
ব্যাকগ্রাউন্ড অ্যাপ্লিকেশন খোলা থাকলেও ব্যাকগ্রাউন্ডে (মিনিমাইজ করা) থাকলে। সাধারণত, ব্যবহারকারী ডিভাইসে "হোম" বোতাম প্রেস করলে, অ্যাপ সুইচার ব্যবহার করে অন্য অ্যাপে পাল্টে নিলে, অথবা অন্য ট্যাবে (ওয়েব) অ্যাপ্লিকেশন খোলা থাকলে এটি ঘটে।
বন্ধ করে দেওয়া হয়েছে ডিভাইস লক করা থাকলে বা অ্যাপ্লিকেশন না চললে।

FCM ব্যবহার করে অ্যাপ্লিকেশন মেসেজ পেলোড পাওয়ার আগে কয়েকটি পূর্বশর্ত পূরণ করতে হবে:

  • অ্যাপ্লিকেশনটি অন্তত একবার খুলতে হবে (FCM-এ রেজিস্ট্রেশন করার জন্য)।
  • iOS-এ, ব্যবহারকারী অ্যাপ সুইচার থেকে অ্যাপ্লিকেশনটি সরিয়ে দিলে, ব্যাকগ্রাউন্ড মেসেজ আবার কাজ করা শুরু করার জন্য এটি ম্যানুয়ালি আবার খুলতে হবে।
  • Android-এ, ব্যবহারকারী ডিভাইস সেটিংস থেকে অ্যাপ জোর করে বন্ধ করে দিলে, মেসেজ কাজ করা শুরু করার জন্য এটি ম্যানুয়ালি আবার খুলতে হবে।
  • ওয়েবে, আপনার ওয়েব পুশ সার্টিফিকেটের সাথে আপনাকে অবশ্যই টোকেনের (getToken() ব্যবহার করে) অনুরোধ করতে হবে।

মেসেজ পাওয়ার জন্য অনুমতি চাওয়া

iOS, macOS, ওয়েব ও Android 13 (বা এর পরের যেকোনও ভার্সন)-এ, আপনার ডিভাইসে FCM পেলোড পাওয়ার আগে, আপনাকে অবশ্যই প্রথমে ব্যবহারকারীর অনুমতি নিতে হবে।

firebase_messaging প্যাকেজটি requestPermission পদ্ধতি ব্যবহার করে অনুমতি চাওয়ার জন্য একটি API প্রদান করে। এই API-তে বেশ কিছু নামযুক্ত আর্গুমেন্ট গ্রহণ করা হয়, যা আপনার অনুরোধ করা অনুমতির ধরন নির্ধারণ করে, যেমন, বিজ্ঞপ্তি পেলোড থাকা মেসেজিং সাউন্ড ট্রিগার করতে বা Siri-কে দিয়ে মেসেজ রিড-আউট করাতে পারবে কিনা। ডিফল্ট হিসেবে, পদ্ধতিটি যুক্তিসঙ্গত ডিফল্ট অনুমতির জন্য অনুরোধ করে। প্রতিটি অনুমতির কাজ কী, তা রেফারেন্স API থেকে সম্পূর্ণ ডকুমেন্টেশন পাওয়া যায়।

শুরু করতে, আপনার অ্যাপ্লিকেশন থেকে পদ্ধতিটি কল করুন (iOS-এ একটি বিল্ট-ইন মোডাল দেখানো হবে, ওয়েবে ব্রাউজারের API ফ্লো ট্রিগার করা হবে):

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

যেহেতু হ্যান্ডলারটি আপনার অ্যাপ্লিকেশন কনটেক্সটের বাইরে নিজস্ব আইসোলেটে রান করে, তাই এটি অ্যাপ্লিকেশন স্টেট আপডেট করতে বা কোনও UI প্রভাবিত করার মতো লজিক এক্সিকিউট করতে পারে না। তবে, আপনি HTTP অনুরোধের মতো লজিক পারফর্ম করতে, IO অপারেশন পারফর্ম করতে (যেমন, লোকাল স্টোরেজ আপডেট করা), অন্যান্য প্লাগ-ইনের সাথে যোগাযোগ করা ইত্যাদি করতে পারবেন।

এছাড়াও, যত তাড়াতাড়ি সম্ভব আপনার লজিক সম্পূর্ণ করার জন্য সাজেস্ট করা হয়। দীর্ঘ, ইনটেনসিভ টাস্ক রান করা হলে ডিভাইসের পারফর্ম্যান্সের উপর প্রভাব পড়ে এবং এর ফলে OS প্রসেস বন্ধ করে দিতে পারে। টাস্ক ৩০ সেকেন্ডের বেশি সময় ধরে চললে, ডিভাইস অটোমেটিক প্রসেস বন্ধ করে দিতে পারে।

ওয়েব

ওয়েবে, একটি জাভাস্ক্রিপ্ট সার্ভিস ওয়ার্কার লেখো যেটি ব্যাকগ্রাউন্ডে রান করে। ব্যাকগ্রাউন্ড মেসেজ ম্যানেজ করতে সার্ভিস ওয়ার্কার ব্যবহার করুন।

শুরু করতে, আপনার web ডিরেক্টরিতে একটি নতুন ফাইল তৈরি করুন এবং এটিকে firebase-messaging-sw.js নামে কল করুন:

// See this file for the latest firebase-js-sdk version:
// https://github.com/firebase/flutterfire/blob/main/packages/firebase_core/firebase_core_web/lib/src/firebase_sdk_version.dart
importScripts("https://www.gstatic.com/firebasejs/10.7.0/firebase-app-compat.js");
importScripts("https://www.gstatic.com/firebasejs/10.7.0/firebase-messaging-compat.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 ভেরিয়েবল এক্সপোজ করতে হবে।

এরপরে, কর্মী রেজিস্টার করতে হবে। index.html ফাইলের মধ্যে, Flutter বুটস্ট্র্যাপ করে এমন <script> ট্যাগ পরিবর্তন করে ওয়ার্কার রেজিস্টার করুন:

<script src="flutter_bootstrap.js" async>
  if ('serviceWorker' in navigator) {
    window.addEventListener('load', function () {
      navigator.serviceWorker.register('firebase-messaging-sw.js', {
        scope: '/firebase-cloud-messaging-push-scope',
      });
    });
  }
</script>

আপনি এখনও পুরনো টেমপ্লেটিং সিস্টেম ব্যবহার করলে, নিম্নলিখিত উপায়ে Flutter-কে বুটস্ট্র্যাপ করা <script> ট্যাগ পরিবর্তন করে ওয়ার্কার রেজিস্টার করতে পারবেন:

<html>
<body>
  <script>
      var serviceWorkerVersion = null;
      var scriptLoaded = false;
      function loadMainDartJs() {
        if (scriptLoaded) {
          return;
        }
        scriptLoaded = true;
        var scriptTag = document.createElement('script');
        scriptTag.src = 'main.dart.js';
        scriptTag.type = 'application/javascript';
        document.body.append(scriptTag);
      }

      if ('serviceWorker' in navigator) {
        // Service workers are supported. Use them.
        window.addEventListener('load', function () {
          // Register Firebase Messaging service worker.
          navigator.serviceWorker.register('firebase-messaging-sw.js', {
            scope: '/firebase-cloud-messaging-push-scope',
          });

          // 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;

          navigator.serviceWorker.register(serviceWorkerUrl).then((reg) => {
            function waitForActivation(serviceWorker) {
              serviceWorker.addEventListener('statechange', () => {
                if (serviceWorker.state == 'activated') {
                  console.log('Installed new service worker.');
                  loadMainDartJs();
                }
              });
            }
            if (!reg.active && (reg.installing || reg.waiting)) {
              // No active web worker and we have installed or are installing
              // one for the first time. Simply wait for it to activate.
              waitForActivation(reg.installing ?? reg.waiting);
            } else if (!reg.active.scriptURL.endsWith(serviceWorkerVersion)) {
              // When the app updates the serviceWorkerVersion changes, so we
              // need to ask the service worker to update.
              console.log('New service worker available.');
              reg.update();
              waitForActivation(reg.installing);
            } else {
              // Existing service worker is still good.
              console.log('Loading app from service worker.');
              loadMainDartJs();
            }
          });

          // If service worker doesn't succeed in a reasonable amount of time,
          // fallback to plaint <script> tag.
          setTimeout(() => {
            if (!scriptLoaded) {
              console.warn(
                'Failed to load app from service worker. Falling back to plain <script> tag.'
              );
              loadMainDartJs();
            }
          }, 4000);
        });
      } else {
        // Service workers not supported. Just drop the <script> tag.
        loadMainDartJs();
      }
  </script>
</body>

এরপরে আপনার Flutter অ্যাপ্লিকেশন রিস্টার্ট করুন। ওয়ার্কার রেজিস্টার করা হবে এবং এই ফাইল ব্যবহার করে ব্যাকগ্রাউন্ড মেসেজ ম্যানেজ করা হবে।

ইন্টার‍্যাকশন ম্যানেজ করা

যেহেতু বিজ্ঞপ্তি একটি দৃশ্যমান ইঙ্গিত, তাই ব্যবহারকারীরা সাধারণত সেটির সাথে ইন্টার‍্যাক্ট করেন (প্রেস করার মাধ্যমে)। Android ও iOS, দু'টি প্ল্যাটফর্মেই ডিফল্ট আচরণ হল অ্যাপ্লিকেশন খোলা। অ্যাপ্লিকেশন বন্ধ করা থাকলে সেটি চালু করা হবে; এটি ব্যাকগ্রাউন্ডে থাকলে সেটি ফোরগ্রাউন্ডে আনা হবে।

বিজ্ঞপ্তির কন্টেন্টের উপর নির্ভর করে, অ্যাপ্লিকেশন খোলার সময় আপনি ব্যবহারকারীর ইন্টার‍্যাকশন ম্যানেজ করতে চাইতে পারেন। যেমন, কোনও বিজ্ঞপ্তির মাধ্যমে নতুন চ্যাট মেসেজ পাঠানো হলে এবং ব্যবহারকারী সেটি প্রেস করলে, অ্যাপ্লিকেশন খোলার সময় আপনি নির্দিষ্ট কথোপকথন খুলতে চাইতে পারেন।

firebase-messaging প্যাকেজ এই ইন্টার‍্যাকশন ম্যানেজ করার দুটি উপায় প্রদান করে:

  • getInitialMessage(): অ্যাপ্লিকেশন বন্ধ করা অবস্থা থেকে খোলা হলে, Future-এর মধ্যে RemoteMessage সহ উত্তর দেওয়া হবে। ব্যবহার করা হয়ে গেলে, RemoteMessage সরিয়ে দেওয়া হবে।
  • onMessageOpenedApp: ব্যাকগ্রাউন্ড থেকে অ্যাপ্লিকেশন খোলা হলে Stream যা RemoteMessage পোস্ট করে।

আপনার ব্যবহারকারীদের জন্য মসৃণ UX নিশ্চিত করতে, দুটি পরিস্থিতিই সামলানোর সাজেশন দেওয়া হয়। নিচে দেওয়া কোডের উদাহরণ থেকে কীভাবে এটি করা যায় তা জানতে পারবেন:

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 using 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 ব্যবহার করে একটি প্রাথমিক ইলাস্ট্রেশন দেখানো হয়েছে।

Messages লোকালইজ করা

আপনি দুটি আলাদা আলাদা উপায়ে লোকালাইজ করা স্ট্রিং পাঠাতে পারবেন:

  • আপনার সার্ভারে প্রতিটি ব্যবহারকারীর পছন্দের ভাষা সেভ করুন এবং প্রতিটি ভাষার জন্য কাস্টমাইজ করা বিজ্ঞপ্তি পাঠান
  • আপনার অ্যাপে লোকালাইজ করা স্ট্রিং এম্বেড করুন এবং অপারেটিং সিস্টেমের বিল্ট-ইন লোকেল সেটিংস ব্যবহার করুন

দ্বিতীয় পদ্ধতিটি কীভাবে ব্যবহার করবেন তা এখানে দেওয়া হল:

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 অ্যাট্রিবিউটে সেগুলি সেট করুন।

    মেসেজ পেলোডটি দেখতে এইরকম হবে:

    {
      "android": {
         "notification": {
           "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";
    

    মেসেজ পেলোডটি দেখতে এইরকম হবে:

    {
      "apns": {
         "payload": {
           "alert": {
             "title-loc-key": "NOTIFICATION_TITLE",
             "loc-key": "NOTIFICATION_MESSAGE"
           }
         }
      }
    }
    

মেসেজ ডেলিভারি ডেটা এক্সপোর্ট করার সুবিধা চালু করা

আরও বিশ্লেষণের জন্য আপনি BigQuery-তে মেসেজ ডেটা এক্সপোর্ট করতে পারবেন। BigQuery আপনাকে BigQuery SQL ব্যবহার করে ডেটা বিশ্লেষণ করতে, অন্য কোনও ক্লাউড প্রোভাইডারে এক্সপোর্ট করতে বা আপনার কাস্টম ML মডেলের জন্য ডেটা ব্যবহার করতে দেয়। BigQuery-তে এক্সপোর্ট করা ডেটার মধ্যে মেসেজের জন্য উপলভ্য সব ডেটা অন্তর্ভুক্ত থাকে। মেসেজের ধরন বা মেসেজটি API বা Notifications composer ব্যবহার করে পাঠানো হয়েছে কিনা, তা দেখার প্রয়োজন হয় না।

এক্সপোর্ট করার সুবিধা চালু করতে, প্রথমে 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 Auth pod যোগ করতে হবে।

ধাপ ১ - বিজ্ঞপ্তি পরিষেবা এক্সটেনশন যোগ করুন

  1. Xcode-এ, ফাইল > নতুন > টার্গেট... বিকল্পে ক্লিক করুন
  2. সম্ভাব্য টার্গেটের একটি তালিকা মোডাল উইন্ডোতে দেখানো হবে; বিজ্ঞপ্তি পরিষেবা এক্সটেনশন বেছে নিতে স্ক্রল করুন বা ফিল্টার ব্যবহার করুন। পরবর্তী বিকল্পে ক্লিক করুন।
  3. প্রোডাক্টের নাম যোগ করুন (এই টিউটোরিয়াল অনুসরণ করতে "ImageNotification" ব্যবহার করুন), Swift অথবা Objective-C বিকল্প বেছে নিন এবং সম্পূর্ণ করুন বিকল্পে ক্লিক করুন।
  4. অ্যাক্টিভেট করুন বিকল্পে ক্লিক করে স্কিম চালু করুন।

ধাপ ২ - Podfile-এ টার্গেট যোগ করুন

Swift

আপনার নতুন এক্সটেনশনের FirebaseMessaging swift package-এ অ্যাক্সেস আছে কিনা তা নিশ্চিত করুন, এটি আপনার Runner টার্গেটে যোগ করে:

  1. নেভিগেটর থেকে, Firebase Apple প্ল্যাটফর্ম SDK যোগ করুন: ফাইল > প্যাকেজ ডিপেন্ডেন্সি যোগ করুন...

  2. প্যাকেজ URL সার্চ বা লিখুন: none https://github.com/firebase/firebase-ios-sdk

  3. প্রোজেক্টে যোগ করুন Runner: প্যাকেজ যোগ করুন

  4. FirebaseMessaging বেছে নিন এবং টার্গেট ImageNotification-এ যোগ করুন: প্যাকেজ যোগ করুন

Objective-C

আপনার নতুন এক্সটেনশনের Firebase/Messaging pod-এ অ্যাক্সেস আছে কিনা তা নিশ্চিত করুন, এর জন্য Podfile-এ এটি যোগ করুন:

  1. নেভিগেটর থেকে, 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 ব্যবহার করে আপনার পড ইনস্টল বা আপডেট করুন।

ধাপ ৩ - এক্সটেনশন হেল্পার ব্যবহার করা

এই পর্যায়ে, সবকিছু এখনও স্বাভাবিকভাবে চলতে থাকবে। শেষ ধাপ হল এক্সটেনশন হেল্পারকে ইনভোক করা।

Swift

  1. নেভিগেটর থেকে, আপনার ImageNotification এক্সটেনশন বেছে নিন

  2. NotificationService.swift ফাইলটি খুলুন।

  3. NotificationService.swift-এর কন্টেন্ট পরিবর্তন করে এগুলি লিখুন:

    import UserNotifications
    import FirebaseMessaging
    
    class NotificationService: UNNotificationServiceExtension {
    
        var contentHandler: ((UNNotificationContent) -> Void)?
        var bestAttemptContent: UNMutableNotificationContent?
    
        override func didReceive(_ request: UNNotificationRequest, withContentHandler contentHandler: @escaping (UNNotificationContent) -> Void) {
            self.contentHandler = contentHandler
            bestAttemptContent = (request.content.mutableCopy() as? UNMutableNotificationContent)
    
            Messaging.serviceExtension().populateNotificationContent(bestAttemptContent!, withContentHandler: contentHandler)
        }
    
        override func serviceExtensionTimeWillExpire() {
            if let contentHandler = contentHandler, let bestAttemptContent = bestAttemptContent {
                contentHandler(bestAttemptContent)
            }
        }
    }
    

Objective-C

  1. নেভিগেটর থেকে, আপনার ImageNotification এক্সটেনশন বেছে নিন

  2. NotificationService.m ফাইলটি খুলুন।

  3. ফাইলের সবচেয়ে উপরে, NotificationService.h-এর ঠিক পরে FirebaseMessaging.h ইমপোর্ট করুন।

    NotificationService.m-এর কন্টেন্ট পরিবর্তন করে এগুলি লিখুন:

    #import "NotificationService.h"
    #import "FirebaseMessaging.h"
    #import <FirebaseAuth/FirebaseAuth-Swift.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 () <NSURLSessionDelegate>
    
    @property(nonatomic) void (^contentHandler)(UNNotificationContent *contentToDeliver);
    @property(nonatomic) 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
    

ধাপ ৪ - পেলোডে ছবি যোগ করুন

আপনার বিজ্ঞপ্তি পেলোডে, আপনি এখন একটি ছবি যোগ করতে পারবেন। আরও জানতে, অনুরোধ পাঠানোর প্রসেস দেখুন।