kamalendu4web
kamalendu4web

Reputation: 31

How to receive data from FCM background push notification to main javascript thread so that those values can be used in coding?

I am working in an application where we are trying to use silent FCM push messaging to get little piece of data from the server. FCM working fine with its foreground / background receiving push notification strategy. I have registered serviceWorker from a .js file and configured the same there so that I can receive the push notification data within that file (Foreground strategy).

Problem starts when application goes off focus. Main thread is not there any more until the application get focused again, serviceWorker is still on the play and it receives the message but now I can not receive that data to main thread.

So I am wondering if there is any way around to get those data back to the main thread once it get focussed.

Main thread code in index.js file

if ("serviceWorker" in navigator) {
  window.addEventListener("load", () => {
    navigator.serviceWorker
      .register("./firebase-messaging-sw.js")
      .then((registration) => {
        firebase.initializeApp(firebaseConfig);
        firebase.analytics();
        console.log(registration, "serviceWorker registered!");
        const messaging = firebase.messaging();
        // messaging.useServiceWorker(registration);
        messaging.onMessage((payload) => {
          console.log("[index.js] Foreground Message received.", payload);
          const notificationTitle = payload.notification.title;
          const notificationOptions = {
            body: payload.notification.body,
            icon: payload.notification.icon,
            imgae: payload.notification.image ? payload.notification.image : "",
            click_action: payload.notification.click_action
              ? payload.notification.click_action
              : "",
          };
          let notification = registration.showNotification(
            notificationTitle,
            notificationOptions
          );
          console.log(notification, "notification");
          // const { id, status, file_url } = payload.data;
          // Store.dispatch(MODIFY_REPORT_STATUS(id, status, file_url));
        });

        messaging
          .getToken({ vapidKey: firebaseConfig.vapIdKey })
          .then((currentToken) => {
            if (currentToken) {
              localStorage.setItem("firebaseToken", currentToken);
            } else {
              localStorage.removeItem("firebaseToken", currentToken);
              console.warn(
                "No registration token available. Request permission to generate one."
              );
            }
          })
          .catch((err) => {
            localStorage.removeItem("firebaseToken", currentToken);
            console.error("An error occurred while retrieving token. ", err);
          });
      });
  });
}

This is the code for firebase-messaging-sw.js

// Import and configure the Firebase SDK
// These scripts are made available when the app is served or deployed on Firebase Hosting
// If you do not serve/host your project using Firebase Hosting see https://firebase.google.com/docs/web/setup
importScripts("https://www.gstatic.com/firebasejs/8.1.1/firebase-app.js");
importScripts("https://www.gstatic.com/firebasejs/8.1.1/firebase-messaging.js");
// importScripts('/__/firebase/init.js');

// const messaging = firebase.messaging();

/**
 * Here is is the code snippet to initialize Firebase Messaging in the Service
 * Worker when your app is not hosted on Firebase Hosting.

 // [START initialize_firebase_in_sw]
 // Give the service worker access to Firebase Messaging.
 // Note that you can only use Firebase Messaging here. Other Firebase libraries
 // are not available in the service worker.
 importScripts('https://www.gstatic.com/firebasejs/8.0.1/firebase-app.js');
 importScripts('https://www.gstatic.com/firebasejs/8.0.1/firebase-messaging.js');

 // Initialize the Firebase app in the service worker by passing in
 // your app's Firebase config object.
 // https://firebase.google.com/docs/web/setup#config-object
 firebase.initializeApp({
   apiKey: 'api-key',
   authDomain: 'project-id.firebaseapp.com',
   databaseURL: 'https://project-id.firebaseio.com',
   projectId: 'project-id',
   storageBucket: 'project-id.appspot.com',
   messagingSenderId: 'sender-id',
   appId: 'app-id',
   measurementId: 'G-measurement-id',
 });

 // Retrieve an instance of Firebase Messaging so that it can handle background
 // messages.
 const messaging = firebase.messaging();
 // [END initialize_firebase_in_sw]
 **/
let click_action = "";
self.addEventListener("push", function (event) {
  console.log("PUSH")
  let dt = event.data.json();
  click_action = event.data.json().notification.click_action
    ? event.data.json().notification.click_action
    : "";
  console.log(click_action, "redirect url");
});

self.addEventListener("notificationclick", function (event) {
  // console.log("Notification clicked!!", event.notifiation);
  var redirect_url = event.notification.click_action;
  event.notification.close();
  event.waitUntil(
    clients
      .matchAll({
        type: "window",
      })
      .then(function (clientList) {
        // console.log(clientList);
        for (var i = 0; i < clientList.length; i++) {
          var client = clientList[i];
          if (client.url === "/" && "focus" in client) {
            return client.focus();
          }
        }
        if (clients.openWindow) {
          return clients.openWindow(click_action);
        }
      })
  );
});

firebase.initializeApp({
  apiKey: "AIzaSyCNcY1KYtQExip4Q2jQwYCDGt5y9NbbPoU",
  authDomain: "hot-foods-2020.firebaseapp.com",
  databaseURL: "https://hot-foods-2020.firebaseio.com",
  projectId: "hot-foods-2020",
  storageBucket: "hot-foods-2020.appspot.com",
  messagingSenderId: "749796496166",
  appId: "1:749796496166:web:379830a07371c9d5d6a7e7",
  measurementId: "G-8L15G3BGP8",
});
const messaging = firebase.messaging();
console.log("messaging from firebase-messaging-sw.js ", messaging);
// If you would like to customize notifications that are received in the
// background (Web app is closed or not in browser focus) then you should
// implement this optional method.
// [START on_background_message]
messaging.onBackgroundMessage(function (payload) {

  console.log(
    "[firebase-messaging-sw.js] Received background message ",
    payload, clients
  );
  // Customize notification here
  const notificationTitle = "Background Message Title";
  const notificationOptions = {
    body: "Background Message body.",
    icon: "/firebase-logo.png",
  };

  self.registration.showNotification(notificationTitle, notificationOptions);
});
// [END on_background_message]

Upvotes: 2

Views: 2147

Answers (2)

AMAL MOHAN N
AMAL MOHAN N

Reputation: 1622

I was able to solve this issue without any code change by simply removing the notification from the request payload.

I changed from this payload

{
    "notification": {
        "title": "Hey there",
        "body": "Subscribe to AMAL MOHAN N youtube channel"
    },
    "to": "your-browser-token",
    "data": {
        "value1": "text",
        "value2": "",
        "value3": "sample3",
        "value4": "sample4"
    }
}

to the the following payload

{
    "to": "your-browser-token",
    "data": {
            "value1": "text",
            "value2": "",
            "value3": "sample3",
            "value4": "sample4"
          }
}

this made the recieveMessage() work for both Foreground and Background messages.`

NB : In this method we have to create notification manually.

hope this helps you guys, I found this in an android forum.

Upvotes: 1

Caco
Caco

Reputation: 11

I don't know if you got a solution. I was struggling with the same problem. I solved it by using client.postMessage. Into firebase-messaging-sw.js I added this:

messaging.onBackgroundMessage(function(payload) {
    const promiseChain = self.clients
            .matchAll({
        type: "window",
        includeUncontrolled: true,
    })
            .then((windowClients) => {
                for (let i = 0; i < windowClients.length; i++) {
                const windowClient = windowClients[i];
                windowClient.postMessage(payload);
            }
            })
    .then(() => {
        return self.registration.showNotification("mynotification title ");
    });
    return promiseChain;
});

And into App.js I added the next listener:

navigator.serviceWorker.addEventListener('message', event => {
    // Add handler here
});

Upvotes: 1

Related Questions