Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Firebase web push notification, on click not working

From days since I am trying to get it done, but I am totally stuck at this point.

Here is the code from my service worker file

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

firebase.initializeApp({
    messagingSenderId: "xxxxxxxxxxxx"
});

var messaging = firebase.messaging();


messaging.setBackgroundMessageHandler(function(payload) {

    console.log('[firebase-messaging-sw.js] Received background message ', payload);
    // Customize notification here
    var notificationTitle = payload.data.title; //or payload.notification or whatever your payload is
    var notificationOptions = {
      body: payload.data.body,
      icon: payload.data.icon,
      image: payload.data.image,

      data: { url:payload.data.openURL }, //the url which we gonna use later
      actions: [{action: "open_url", title: "View"}]
    };

    return event.waitUntil(self.registration.showNotification(notificationTitle,
      notificationOptions));
});

 self.addEventListener('notificationclick', function(event) {


    console.log('event = ',event);
    event.notification.close();
    event.waitUntil(clients.openWindow(event.notification.data.url));

    switch(event.action){
      case 'open_url':
        window.open(event.notification.data.url);
      break;
      case 'any_other_action':
        window.open(event.notification.data.url);
      break;
    }


}, false);

And data is in this format

$data=[
        'title' => 'message title',
        'body' => 'description body',
        'icon' => 'https://i.ytimg.com/vi/gXSyP9ga-ag/hqdefault.jpg',
        'image'=>'https://i.ytimg.com/vi/gXSyP9ga-ag/mqdefault.jpg',
        'openURL'=>'https://google.com'
      ];

Now there are many issue.

  • when push notification body is clicked on mobile, it does not open the url, but only dismisses it (only clicking action button opens link

  • I did some reading online and found that

    event.waitUntil(clients.openWindow(event.notification.data.url));
    

    Does not work with safari and safari iPhone, can someone help me find out how to implement a click even listener that will work with apple devices?

Any help would be appreciated

like image 996
Ganesh Avatar asked May 15 '19 20:05

Ganesh


2 Answers

After searching through many solutions I figured out myself. Here's full working example:

// firebase-messaging-sw.js (client side)

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

self.addEventListener('notificationclick', function (event) {
  console.debug('SW notification click event', event)
  const url = '<get your url from event>'
  event.waitUntil(
    clients.matchAll({type: 'window'}).then( windowClients => {
        // Check if there is already a window/tab open with the target URL
        for (var i = 0; i < windowClients.length; i++) {
            var client = windowClients[i];
            // If so, just focus it.
            if (client.url === url && 'focus' in client) {
                return client.focus();
            }
        }
        // If not, then open the target URL in a new window/tab.
        if (clients.openWindow) {
            return clients.openWindow(url);
        }
    })
);
})

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

const messaging = firebase.messaging();

messaging.onBackgroundMessage(function(payload) {
  console.log('[firebase-messaging-sw.js] Received background message ', payload);
})

Here is the code for NodeJS side:

var admin = require("firebase-admin");
// This is a specific account key file generated through the firebase UI
var serviceAccount = require("./serviceAccountKey.json");

admin.initializeApp({
  credential: admin.credential.cert(serviceAccount),
});
const payload = {
  "token": "FCM TOKEN HERE",
  "notification": {
    "title":"James",
    body: '14100000'
  },
  "webpush": {
    "fcm_options": {
        "link": "https://google.com"
    },
  },
};
admin.messaging().send(payload).then(res => {
  console.log('SUCCESS ', res);
}).catch(err => {
  console.log(err);
}).finally(() => {
  process.exit(0);
});

The problem is if I put notificationclick on the bottom, it doesn't fire, really don't know why, then I move it to the top and it works. I can send push notification from server (using firebase-admin), and push notification will be shown (when app is in background), click the notification open the link I want.

like image 113
Duc Trung Mai Avatar answered Sep 20 '22 00:09

Duc Trung Mai


You are using data messages, but you need to use notification messages. See: https://firebase.google.com/docs/cloud-messaging/js/receive

Because data messages don't support fcm_options.link, you are recommended to add a notification payload to all data messages. Alternatively, you can handle notifications using the service worker.

For an explanation of the difference between notification and data messages, see Message types.

This is the JSON payload of a working notification. The click_action is for handling clicks.

{
  "data": {
    "badge": "23",
    "b": "xxxx",
    "t": "yyyy",
    "android_channel_id": "com.example.fcm"
  },
  "from": "11111111111",
  "notification": {
    "title": "Title",
    "body": "Body",
    "icon": "https://example.com/icon.png",
    "click_action": "https://example.com"
  },
  "collapse_key": "do_not_collapse"
}
like image 23
Ralf Avatar answered Sep 20 '22 00:09

Ralf