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?
Related
I'm currently trying to make a postMessage() triggered from a push notification work correctly. Currently, I've got a PWA which has Firebase push notifications. When a notification is sent and clicked, the PWA is launched (if it's installed) and a postMessage() is sent.
However, the postMessage() doesn't get received by the client. If the app is in the foreground, it works as expected.
If the all is in the background though, it doesn't catch the postMessage(). I was wondering if I needed to listen to some kind of load event in my main sw.js file before sending the postMessage() - but I'm not sure.
My firebase-message-sw.js file is as follows:
messaging.onBackgroundMessage(function(payload) {
console.log('[firebase-messaging-sw.js] Received background message ', payload);
// Customize notification here
// self.addEventListener('load', (e) => {
console.log(`page has loaded | load event | firebase-messaging-sw.js`);
const channel = new BroadcastChannel('sw-messages');
channel.postMessage({
title: payload.notification.title,
body: payload.notification.body,
image: payload.notification.image,
// icon: event.notification.icon,
}, "*")
// })
})
My sw.js file is like this:
addEventListener('notificationclick', event => {
event.notification.close();
const urlToOpen = new URL("/settings", self.location.origin).href;
const promiseChain = clients.matchAll({
type: 'window',
includeUncontrolled: true
}).then((windowClients) => {
let matchingClient = null;
for (let i = 0; i < windowClients.length; i++) {
const windowClient = windowClients[i];
if (windowClient.url === urlToOpen) {
matchingClient = windowClient;
break;
}
}
if (matchingClient) {
return matchingClient.focus();
} else {
console.log(`opening new window`);
return clients.openWindow(urlToOpen);
}
});
event.waitUntil(promiseChain);
console.log("promiseChain | sw.js");
const channel = new BroadcastChannel('sw-messages');
channel.postMessage({
title: event.notification.title,
body: event.notification.body,
image: event.notification.image,
icon: event.notification.icon,
})
});
NOTE: This all works as required when the website is viewed in a browser, and not a PWA.
Does anyone has any suggestions/recommendations on what I should do?
Thanks in advance.
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.
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'm trying to build a web application that will send push notifications to a user who subscribes to it (testing on Samsung Internet). However, I'm facing an issue where after several hours, the phone stops receiving the push notifications, and I will need to re-open the web application and re-subscribe to resume receiving push notifications. Below is the code for my service worker and its registration:
Service Worker:
var windowActive = true;
var numMessages = 0;
var sAdder;
self.addEventListener('push', function(event) {
console.log('[Service Worker] Push Received.');
// console.log(`[Service Worker] Push had this data: "${event.data.text()}"`);
console.log(windowActive);
numMessages++;
if(numMessages == 1) {
sAdder = "";
} else {
sAdder = "s";
}
var title = 'Convers8te';
var options = {
body: numMessages + ' message' + sAdder + ' received!',
icon: '/images/logo/8-icon.png',
badge: '/images/badge.png',
tag: 'c8t',
};
if(windowActive == false) {
event.waitUntil(self.registration.showNotification(title, options));
}
});
self.addEventListener('notificationclick', function(event) {
console.log('[Service Worker] Notification click Received.');
event.notification.close();
numMessages = 0;
event.waitUntil(
clients.openWindow('')
);
});
self.addEventListener('message', function (evt) {
windowActive = evt.data['windowActive'];
console.log('postMessage received', evt.data);
});
Registration:
function subscribeUser() {
const applicationServerKey = urlB64ToUint8Array(applicationServerPublicKey);
swRegistration.pushManager.subscribe({
userVisibleOnly: true,
})
.then(function(subscription) {
console.log('User is subscribed.');
updateSubscriptionOnServer(subscription);
isSubscribed = true;
updateBtn();
})
.catch(function(err) {
console.log('Failed to subscribe the user: ', err);
updateBtn();
});
}
Update subscription on server then sends the push token to the server to be used through the Firebase service.
I've tried several things such as lengthening the session duration, and testing on several other devices but it seems to stop receiving push notifications after several hours.
Also, a side question is whether it is possible for push notifications work even when the Samsung Internet explorer app is closed? Currently they only work for me when the tab is closed, but not when the entire app is closed.
Thanks for taking the time to read and help!
This code show my notifications, all is good, but in the notification popup i see no icon, and click notification just close it and not open window. This code i get from this (Google's tutorial).
importScripts('https://www.gstatic.com/firebasejs/3.5.2/firebase-app.js');
importScripts('https://www.gstatic.com/firebasejs/3.5.2/firebase-messaging.js');
firebase.initializeApp({
'messagingSenderId': 'my id'
});
const messaging = firebase.messaging();
messaging.setBackgroundMessageHandler(function(payload) {
var title = '';
var body = '';
if(payload && payload.notification) {
if(payload.notification.body) {
body = payload.notification.body;
if(payload.notification.title) {
title = payload.notification.title;
}
}
}
return self.registration.showNotification(title, {
body: body,
icon: '/img/logos/logo-short-blue.png'
});
});
self.addEventListener('notificationclick', function(event) {
event.notification.close();
var appUrl = '/' + event.notification.data.actionUrl;
event.waitUntil(clients.matchAll({
includeUncontrolled: true,
type: 'window'
}).then( activeClients => {
if (activeClients.length > 0) {
activeClients[0].navigate(appUrl);
activeClients[0].focus();
} else {
clients.openWindow(appUrl);
}
})
);
});
You have to use click_action as url and icon fields on server side, while forming payload of push-message.
from google's guide :
Click actions support only secure HTTPS URLs.