Click action not working on notification pwa - javascript

I am working pwa where notifications are coming fine.But when i click on notification nothing happens. I know this question already asked. My code is below:-
firebase.initializeApp({
'messagingSenderId': 'SEnder_id'
});
// Retrieve an instance of Firebase Messaging so that it can handle background
// messages.
const messaging = firebase.messaging();
messaging.setBackgroundMessageHandler(function(payload) {
//console.log('[firebase-messaging-sw.js] Received background message ', payload);
// Customize notification here
const notificationTitle = 'Background Message Title';
const notificationOptions = {
body: 'Background Message body.',
icon: '/itwonders-web-logo.png',
data: {
click_action: payload.notification.click_action
}
};
// Notifcation click event
self.addEventListener('notificationclick', function (event) {
event.notification.close();
clients.openWindow("https://youtu.be/PAvHeRGZ_lA"); //even simple static link not opening
});
return self.registration.showNotification(notificationTitle,
notificationOptions);
});
I am also getting click_action value when notification come.

Related

How to play notification sound in service worker?

I'm using Firebase Cloud Messaging to send notifications to users of a web app.
Here is my current setup for firebase-messaging-sw.js
importScripts('https://www.gstatic.com/firebasejs/5.5.0/firebase-app.js');
importScripts('https://www.gstatic.com/firebasejs/5.5.0/firebase-messaging.js');
firebase.initializeApp({
'messagingSenderId': '123456'
});
const messaging = firebase.messaging();
messaging.setBackgroundMessageHandler(function(payload) {
console.log('[firebase-messaging-sw.js] Received background message ', payload);
// Customize notification here
const title = 'New Order';
const notificationOptions = {
body: 'Background Message body.',
renotify: true,
tag: "newOrder",
vibrate: [200, 100, 200, 100, 200, 100, 200],
requireInteraction: true,
};
return self.registration.showNotification(title,
notificationOptions);
});
self.addEventListener('notificationclick', function(event) {
let url = 'https://dashboard.inhouseorders.io';
event.notification.close(); // Android needs explicit close.
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);
}
})
);
});
I've seen PWAs like Google Chat where the notification will play a custom sound. I'm assuming that would be done here in the service worker but how can I do that?
I've used Howler in the past to play sounds in the browser but that requires some user interaction before it will play the sound. So how can I play a sound in the service worker?

Web foreground push notification is not popping up integrated using Firebase in Reactjs

I have use fcm for push notification in my reactjs web application. I am able to get notification if the the web application is running in the background. But not able to get notification while my application is actively running in foreground.
Firebase initialization is perfectly done in my project,because I am successfully getting push notification in the background.
firebase-messaging-sw.js
importScripts('https://www.gstatic.com/firebasejs/6.3.4/firebase-app.js');
importScripts('https://www.gstatic.com/firebasejs/6.3.4/firebase-messaging.js');
firebase.initializeApp({
'messagingSenderId': '337889493107'
});
const messaging = firebase.messaging();
messaging.setBackgroundMessageHandler(function (payload) {
const data = JSON.parse(payload.data.notification);
const notificationTitle = data.title;
const notificationOptions = {
body: data.body,
icon: '/favicon.png'
};
return self.registration.showNotification(notificationTitle,
notificationOptions);
});
messaging.onMessage(function(payload) {
const data = JSON.parse(payload.data.notification);
const notificationTitle = data.title;
const notificationOptions = {
body: data.body,
icon: '/favicon.png'
};
return self.registration.showNotification(notificationTitle,
notificationOptions);
});
Do I need to do any further modification to my foreground method messaging.onMessage or do I need to do any more configuration. Plz help me out
Please try to use Notifications API, instead of the Service Worker API.
messaging.onMessage(function(payload) {
const notificationTitle = payload.notification.title;
const notificationOptions = {
body: payload.notification.body,
icon: payload.notification.icon,
};
if (!("Notification" in window)) {
console.log("This browser does not support system notifications.");
} else if (Notification.permission === "granted") {
// If it's okay let's create a notification
var notification = new Notification(notificationTitle,notificationOptions);
notification.onclick = function(event) {
event.preventDefault();
window.open(payload.notification.click_action , '_blank');
notification.close();
}
}
});

I can't store data from setBackgroundMessageHandler

I'm using firebase for pushing notification. When I get the notification in the background, I get data. I want to save this data in the local storage, but I get this error
TypeError: Cannot read property 'setItem' of undefined
importScripts('https://www.gstatic.com/firebasejs/3.9.0/firebase-app.js');
importScripts('https://www.gstatic.com/firebasejs/3.9.0/firebase-messaging.js');
firebase.initializeApp({
messagingSenderId: '628214501041'
});
const messaging = firebase.messaging();
messaging.setBackgroundMessageHandler(function (payload) {
console.log('[firebase-messaging-sw.js] Received background message ', payload);
var notificationTitle = 'Background Message Title';
var notificationOptions = {
body: 'Background Message body.',
};
return self.registration.showNotification(notificationTitle,
notificationOptions);
});
self.addEventListener('push', function (event) {
var pushData = event.data.json();
try {
if(self.window.localStorage){
self.localStorage.setItem('notificationData' , JSON.stringify(pushData) ) ;
// }
}
catch (err) {
console.log('Push error happened:', err);
}
});
The self variable you're using in your code is not something that is defined by default.
But from your code, you're probably looking for:
if(self.window.localStorage) {
self.window.localStorage.setItem('notificationData' , JSON.stringify(pushData) ) ;
}
So the change there is using self.window.localStorage, instead of self.localStorage in the second line.
Well, you can't access the local storage or the session storage from your service worker because it have no access to the DOM.
You should use CacheAPI
Or for persisting data and access it from your service worker and window instance use:
IndexedDB
This is in the lifecyle of your service worker and can also be accessed by the window object.

FCM Push notifications arrive twice if the browser is in background

I've set up a simple push notification site, the notifications arrive okay if the browser is in foreground.
The problem begins if the browser is in background: the notification arrives twice, one styled with image and other settings set and the other has only title and body message.
Content of the service worker:
importScripts('https://www.gstatic.com/firebasejs/3.5.2/firebase-app.js');
importScripts('https://www.gstatic.com/firebasejs/3.5.2/firebase-messaging.js');
// Initialize the Firebase app in the service worker by passing in the
// messagingSenderId.
firebase.initializeApp({
'messagingSenderId': '...'
});
const messaging = firebase.messaging();
messaging.setBackgroundMessageHandler(function(payload) {
console.log('[firebase-messaging-sw.js] Received background message ',
return null;
});
self.addEventListener('install', function (event) {
event.waitUntil(skipWaiting());
});
self.addEventListener('activate', function (event) {
event.waitUntil(clients.claim());
});
self.addEventListener('push', function (event) {
var pushData = event.data.json();
try {
var notificationData = pushData.data;
notificationData.data = JSON.parse(notificationData.data);
console.log(notificationData);
self.registration.showNotification(pushData.notification.title, notificationData);
}
catch (err) {
console.log('Push error happened: ', err);
}
});
Client side js:
firebase.initializeApp(firebaseConfig);
const messaging = firebase.messaging();
messaging.onMessage(function (payload) {
console.log("notification recieved");
return null;
});
self.addEventListener('push', function (event) {
console.log("window push stuff");
return null;
});
Thanks!
Simplest way to 100% avoid multiple notifications is adding "tag", eg.:
var options = {
body: "text",
tag: "notification-1"
};
self.registration.showNotification("title", options)
The problem can be solved with adding this line to the messaging.setBackgroundMessageHandler event:
self.registration.hideNotification();
This way, the default notification won't show and you have to show your notification in the self.addEventListener event.
It took for me around two weeks for me to understand and solve this issue. Hope that will save time for other people:
Firebase supports two types of push notifications:
Display notifications that FCM SDK handles automatically Data
Data messages, which are handled by the client app
Firebase cloud messaging UI has many advantages like advanced targeting by countries, devices, languages, and more. But it allows sending URLs only inside the data custom field.
Message sent from Firebase Console UI looks this way:
{
notification: {
title: "New Test",
body: "This is test",
},
data: {
url: 'someurl.com',
},
};
The notification comes twice when the service worker handles it and a second time when FCM SDK automatically does it.
I didn't found a way to disable auto handling of notification and in the frontend and used Firebase Functions to send it only as data message:
{
data: {
title: "New Test",
body: "This is test",
url: 'someurl.com',
},
};
So, if you want to pass custom URL to push notification, you will need to send it from your own server or using firebase functions.
This is how I get Firebase Cloud Messaging Notifications to work in Progresse Web Apps on Android Devices with those requirements:
Push notifications should only appear once in the status bar as well
The number of notifications should be highlighted at on the PWA app icon
The notification in the status bar should contain:
A small badge with the app icon
The actual app icon
A noticiation title
A notification body
Open the PWA on tap
firebase-messaging.sw.js
Don't add any cdoe or onBackgroundMessage() handler to this file. My file is nothing more but
//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.3.0/firebase-app.js');
importScripts('https://www.gstatic.com/firebasejs/8.3.0/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.
if (firebase.messaging.isSupported()) {
const messaging = !firebase.apps.length
? firebase.initializeApp(firebaseConfig).messaging()
: firebase.app().messaging();
Server side job to send notifications
The content and structure of the messaging payload is key. Put your notification object into a webpush object. Do not add a data object in order to avoid dubplicate notifications with incomplete content.
Make sure your badge is 24x24px png that contains only white content on a transparent background.
var message = {
webpush: {
notification: {
title: "Let's Join App", // Your message title
body: messageBody, // Your message body
icon: "./img/icons/android-chrome-192x192.png", // Your App icon, up to 512x512px, any color
badge: "./img/icons/badge.png", // Your app badge, 24x24px, white content on transparent background
},
fcmOptions: {
link: "https://www.letsjoin.app", // Your Link
},
},
token,
};
// Send a message to the device corresponding to the provided
// registration token.
await admin
.messaging()
.send(message)
.then((response) => {
// Response is a message ID string.
console.log("Successfully sent message");
})
.catch((error) => {
console.log("Error sending message:", error.errorInfo.message);
});
};

Fcm serviceworker receive message in background but code not executed

var config = {
messagingSenderId: "18????????2"
};
firebase.initializeApp(config);
const messaging = firebase.messaging();
messaging.setBackgroundMessageHandler(function (payload) {
$.ajax({
type: "POST",
dataType: "json",
data: { notificationID: payload.data.notificationID },
url: "https://myapi/somerestservice",
success: function (data) {
console.log("remove notification status : " + data.Status + " - Message : " + data.Message);
}
});
const notificationTitle = payload.notification.title;
const notificationOptions = {
body:payload.notification.body,
};
return self.registration.showNotification(notificationTitle, notificationOptions);
I receive messages in background without any errors and message appear in browser perfectly
My problem is I need to execute some code to delete data from db, but any code I added in setBackgroundMessageHandler not fired when message received
is there any event fired when message received in background
(in foreground I use onMessage and its work nice)
If the notification key is set on the message when you send the HTTP/XMPP request (e.g. from your backend), the message handler registered with setBackgroundMessageHandler will not be called. Firebase will handle the message for you and display it as-is.
If you need to do something when the message is received while you app is in the background, you can instead use the data key on your message; if the notification key is omitted, the handler registered with setBackgroundMessageHandler will be called and you can handle the payload and customize the notification:
messaging.setBackgroundMessageHandler(function(payload) {
console.log('[firebase-messaging-sw.js] Received background message ', payload);
// Do you AJAX request here.
// Customize and show your notification
const notificationTitle = payload.data.title,
const notificationOptions = {
body: payload.data.body,
icon: payload.data.icon
};
return self.registration.showNotification(notificationTitle,
notificationOptions);
});
NB: In addition to displaying the notification yourself, you will also have to manually handle clicking and closing events.
To send the message:
https://fcm.googleapis.com/fcm/send
Content-Type:application/json
Authorization:key=AIzaSyZ-1u...0GBYzPu7Udno5aA
{ "data": {
"title": "Hello",
"body": "How are you?",
"icon": "https://..."
},
"to" : "bk3RNwTe3H0:CI2k_HHwgIpoDKCIZvvDMExUdFQ3P1..."
}
This part of the official docs can be a bit confusing, but some clarifications about when the two message handlers are called can be found here: https://sentinelstand.com/article/handling-firebase-notification-messages-in-your-web-app

Categories