firebase set background message handler - firebase

I have been trying to customise notification message in front end, i.e if a field is not set send in notification, I am trying to add it.
importScripts('https://www.gstatic.com/firebasejs/5.0.4/firebase-app.js');
importScripts('https://www.gstatic.com/firebasejs/5.0.4/firebase-messaging.js');
var config = {
apiKey: "x",
authDomain: "y",
databaseURL: "z",
projectId: "a",
storageBucket: "b",
messagingSenderId: "1"
};
firebase.initializeApp(config);
const messaging = firebase.messaging();
console.log('came here');
console.log(messaging.bgMessageHandler);
console.log(messaging.setBackgroundMessageHandler,'dsafdsadasfd')
messaging.setBackgroundMessageHandler(function(payload) {
console.log('[firebase-messaging-sw.js] Received background message ', payload);
// Customize notification here
var notificationTitle = 'Background Message Title';
var notificationOptions = {
body: 'Background Message body.',
icon: '/firebase-logo.png'
};
console.log(notificationOptions)
return self.registration.showNotification(notificationTitle,
notificationOptions);
});
console.log(messaging.bgMessageHandler);
while executing the above code, I am not getting an console of [firebase-messaging-sw.js] Received background message ', payload, even though i am getting notification.
Why is the setBackgroundMessageHandler not working?

It looks like problem within the json request that you made to send the message while app is running in background.
Note: If you set notification fields in your HTTP or XMPP send request, those values take precedence over any values specified in the service worker.
https://firebase.google.com/docs/cloud-messaging/js/topic-messaging
So,Following format won't call the background handler :
{
to: "e-DLMv........._DiL",
notification: {
body: "Backgound-Message"
}
}
Send message with notification inside data (It will work) :
{
to: "e-DLMv........._DiL",
data: {
notification: {
body: "Backgound-Message"
}
}
}

Related

Firebase Cloud Messaging not working with Samsung Internet

I'm setting up Firebase Cloud Messaging to do push notifications on the web. It works but only with Chrome (Windows and Android) and Firefox(Android) so far. It's not working on Samsung Internet Browser (the browser that comes pre-installed on Samsung's phones) and I haven't gotten a chance to test on iOS so far.
I've tried adding the sender id as gcm_sender_id to the Cloud Function I'm using as well as to the manifest.json file to no avail. Below is how the notification body is set up.
// Create notification content
const notification = admin.messaging().Notification = {
title : 'My test Title',
body : `Lorem Ipsum Dolor`,
};
const payload = admin.messaging().Message = {
notification,
webpush:{
notification : {
vibrate: [200, 100, 200],
icon: 'https://www.goodhousekeeping.com/life/pets/g4531/cutest-dog-breeds/', //A random dog photo
fcm_options: {
link: 'https://www.youtube.com',
gcm_sender_id : '<SENDER_ID>',
},
},
},
topic: '<TOPIC>'
};
//Send notification
return admin.messaging().send(payload);
Is there anything I can do to get this to work on Samsung Internet? Service Workers have been supported since v4 and the device has v9. It should be noted that even on the devices that receive it, when I click on it, it doesn't open up the website I set in fcm_options nor does it follow the vibrate pattern but it does load the icon.
UPDATE: As of April 2020 FCM is completely incompatible with iOS Chrome and Safari
So I know this probably isn't helpful but it 'magically' started working today. The browser version is Samsung Internet v10.
firebase-messaging-sw.js
// 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/7.13.2/firebase-app.js');
importScripts('https://www.gstatic.com/firebasejs/7.13.2/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: '',
authDomain: '',
databaseURL: '',
projectId: '',
storageBucket: '',
messagingSenderId: '',
appId: '',
measurementId: ''
});
// Retrieve an instance of Firebase Messaging so that it can handle background
// messages.
const messaging = firebase.messaging();
messaging.setBackgroundMessageHandler(payload => {
console.log('[firebase-messaging-sw.js] Received background message ', payload);
// Customize notification
const notificationTitle = payload.data.title;
const notificationOptions = {
body: payload.data.body,
priority: payload.data.priority,
vibrate: payload.data.vibrate,
icon: payload.data.icon,
click_action: payload.data.link,
link: payload.data.link
};
return self.registration.showNotification(notificationTitle,
notificationOptions);
});
//Open browser window or focus it if it is open on notification click
self.addEventListener('notificationclick', function(event) {
event.notification.close();
event.waitUntil(self.clients.openWindow('www.yourwebsitehere.com'));
});
Cloud function to send notifications
//Sends notifications to users when the statistics document is updated
exports.sendNotifications = functions.firestore.document('restaurant/statistics').onUpdate(async (snapshot,context) =>{
//Get updated document data
const updatedData = snapshot.after.data();
const payload = admin.messaging().Message = {
data: {
title: updatedData.title,
body : updatedData.body,
icon: updatedData.icon,
link: updatedData.link,
vibrate: "[300, 200, 300]",
priority: "high"
},
topic: 'statistics'
}
return admin.messaging().send(payload);
});

Firebase Cloud Messaging click_action not working

I am sending notification from Firebase console to web application (Firebase). When I am sending a POST request from POSTMAN, I am able to navigate to the URL when I click on the notification. But when I am sending it from Firebase console I am not able to open the URL. Also, I need to add my logo as my Icon to the notification.
POSTMAN
{
"notification": {
"title": "Push notification test",
"body": "It works! 🎉",
"icon": "https://soft-ing.info/img/firebase.png",
"click_action": "https://google.com"
},
"to": "dLXCbmVCh5Y:APA91bGmFN7BUsKqwWFokyoBsoph6k4EhBQEflwJLFrPaUzTceYhAPYfFf8LqTRBVJGCA0gWS_0k0DUCeJBa7jdopIyjFQNprtp3lkQgLmUNRUibLIIMxAuBZeXuHTqaU-BA4QwbekN6"
}
Service Worker File Code
messaging.setBackgroundMessageHandler(function(payload) {
console.log('[firebase-messaging-sw.js] Received background message ', payload);
// Customize notification here
const notificationTitle = payload.data.title;//'Background Message Title';
const notificationOptions = {
body: payload.data.body,//'Background Message body.',
icon: payload.data.icon,
image : payload.data.image,
data:{
time: new Date(Date.now()).toString(),
click_action : payload.data.click_action
}
};
return self.registration.showNotification(notificationTitle,notificationOptions);
});
self.addEventListener("notificationclick", (event) => {
event.waitUntil(async function () {
const allClients = await clients.matchAll({
includeUncontrolled: true
});
let chatClient;
let appUrl = 'https://www.google.com';
for (const client of allClients) {
//here appUrl is the application url, we are checking it application tab is open
if(client['url'].indexOf(appUrl) >= 0)
{
client.focus();
chatClient = client;
break;
}
}
if (!chatClient) {
chatClient = await clients.openWindow(appUrl);
}
}());
});
There's some discrepancy in the above two snippets you shared.
In your case body: payload.data.body should be body: payload.notification.body, you need to do similarly for other places in service worker since that's how you are sending the request.

FCM Web Push Notifications - can't obtain token

This is really nocking me out after spending with such easy thing ver two days:
I'm trying to implement FCM Web browser Push Notifications and I went through the google docs several times as well as I watched all official videos on youtube. It is really easy to get the Token but for some reason it crashes in Firebase's JS code.
Here is my HTML/JS code here:
<html>
<head>
<title>Web Push Test 2</title>
<script src="/vendors/jquery/dist/jquery.min.js"></script>
<script src="https://www.gstatic.com/firebasejs/4.13.0/firebase-app.js"></script>
<script src="https://www.gstatic.com/firebasejs/4.13.0/firebase-messaging.js"></script>
</head>
<body>
<button type="button" id="subscribe">Subscribe</button><br />
<script src="https://www.gstatic.com/firebasejs/4.13.0/firebase.js"></script>
<script>
var config = {
apiKey: "AIzaSyBgYGotOm09UkhERqVPriV1XNhymxracno",
authDomain: "******-b6f9c.firebaseapp.com",
databaseURL: "https://******-b6f9c.firebaseio.com",
projectId: "*******-b6f9c",
storageBucket: "******-b6f9c.appspot.com",
messagingSenderId: "333638181210"
};
firebase.initializeApp(config);
if ('Notification' in window) {
console.log("Notification is in window.");
var messaging = firebase.messaging();
messaging.usePublicVapidKey("BE0MvVZ0zyTYGmeNIdj4A8XZZ50OKaZL90xmXbIVfufcMuPb0lAUC99426aBPrAEPHAWYeMbOTpHbcM3OiySEcs");
messaging.onMessage(function(payload) {
console.log("Message received. ", payload);
});
messaging.onTokenRefresh(function() {
messaging.getToken().then(function(refreshedToken) {
console.log('Token refreshed.');
setTokenSentToServer(false);
sendTokenToServer(refreshedToken);
}).catch(function(err) {
console.log('Unable to retrieve refreshed token ', err);
showToken('Unable to retrieve refreshed token ', err);
});
});
if (Notification.permission === 'granted') {
console.log("Permission is granded.");
subscribe();
}
$('#subscribe').on('click', function () {
console.log("Subscribe fired.");
subscribe();
});
}
function subscribe() {
messaging.requestPermission().then(function() {
console.log('Notification permission granted.');
messaging.getToken().then(function(currentToken) {
if (currentToken) {
sendTokenToServer(currentToken);
} else {
console.log('No Instance ID token available. Request permission to generate one.');
setTokenSentToServer(false);
}
}).catch(function(err) {
console.log('An error occurred while retrieving token. ', err);
showToken('Error retrieving Instance ID token. ', err);
setTokenSentToServer(false);
});
}).catch(function(err) {
console.log('Unable to get permission to notify.', err);
});
}
window.is_sentToServer = false
function setTokenSentToServer(sent) {
window.is_sentToServer = sent
}
function showToken(currentToken) {
console.log('Token: '+currentToken);
}
function sendTokenToServer(currentToken) {
$.post('/?c=push&a=save_subscription', {token: currentToken}, function(data){
console.log('Token added...');
setTokenSentToServer(true);
});
}
</script>
</body>
When I run the page, I get the following error:
An error occurred while retrieving token. TypeError: Cannot read property 'buffer' of undefined
And the crash point of firebase JS is here:
https://www.gstatic.com/firebasejs/messaging/dist/index.esm.js
function isTokenStillValid(pushSubscription, publicVapidKey, tokenDetails) {
if (!isArrayBufferEqual(publicVapidKey.buffer, tokenDetails.vapidKey.buffer)) {
return false;
}
var isEndpointEqual = pushSubscription.endpoint === tokenDetails.endpoint;
var isAuthEqual = isArrayBufferEqual(pushSubscription.getKey('auth'), tokenDetails.auth);
var isP256dhEqual = isArrayBufferEqual(pushSubscription.getKey('p256dh'), tokenDetails.p256dh);
return isEndpointEqual && isAuthEqual && isP256dhEqual;
}
So as I can understand so far - the tokenDetails.vapidKey variable is undefined, that's is why it can't read the buffer size, but the question is - why?
I double checked that all my provided Keys are valid but can't figure out what could be wrong here...
Many thanks to anyone who could help me out with this
I'm running that test on localhost as it is shown in original YouTube tutorial and I didn't forget to create the firebase-messaging-sq.js which looks like this:
// firebase-messaging-sw.js
importScripts('https://www.gstatic.com/firebasejs/4.13.0/firebase-app.js');
importScripts('https://www.gstatic.com/firebasejs/4.13.0/firebase-messaging.js');
var config = {
apiKey: "AIzaSyBgYGotOm09UkhERqVPriV1XNhymxracno",
authDomain: "*****-b6f9c.firebaseapp.com",
databaseURL: "https://******-b6f9c.firebaseio.com",
projectId: "*******-b6f9c",
storageBucket: "*****-b6f9c.appspot.com",
messagingSenderId: "333638181210"
};
firebase.initializeApp(config);
const messaging = firebase.messaging();
messaging.usePublicVapidKey("BE0MvVZ0zyTYGmeNIdj4A8XZZ50OKaZL90xmXbIVfufcMuPb0lAUC99426aBPrAEPHAWYeMbOTpHbcM3OiySEcs");
messaging.setBackgroundMessageHandler(function (payload) {
console.log('Handling background message ', payload);
return self.registration.showNotification(payload.notification.title, {
body: payload.notification.body
});
});
This was a bug in Firebase SDK. A thorough explanation of the issue is in the PR here.
The fix will be in version 5.0.2 of the SDK. It should be out later today or tomorrow.
If you don't want to update, then a workaround is to clear your application data. This will force the SDK to regenerate your token. You can do this in Chrome by opening the Developer Console, going to the Application tab, selecting "Clear storage" from the menu on the left, and clicking the "Clear site data" button at the bottom.

Vue pwa with firebase cloud messaging not working properly

im trying the following code:
navigator.serviceWorker.register('service-worker.js')
.then((registration) => {
const messaging = firebase.messaging().useServiceworker(registration)
console.log(messaging)
messaging.requestPermission().then(function () {
console.log('Notification permission granted.')
messaging.getToken().then(function (currentToken) {
if (currentToken) {
console.log(currentToken)
}
})
})
})
my manifest:
{
"name": "Herot-Eyes",
"short_name": "herot-eyes",
"gcm_sender_id": "103953800507",
"icons": [
{
"src": "/static/img/icons/herot-eyes-192x192.png",
"sizes": "192x192",
"type": "image/png"
},
{
"src": "/static/img/icons/herot-eyes-512x512.png",
"sizes": "512x512",
"type": "image/png"
},
{
"src": "/static/img/icons/apple-touch-icon-180x180.png",
"sizes": "180x180",
"type": "image/png"
}
],
"start_url": "/",
"display": "fullscreen",
"orientation": "portrait",
"background_color": "#000000",
"theme_color": "#2196f3"
}
what is going wrong? my console.log(messaging) is returning a factory error, the following:
bad-push-set : "The FCM push set used for storage / lookup was not not
a valid push set string." bad-scope
"The service worker scope must be a string with at least one
character." bad-sender-id
"Please ensure that 'messagingSenderId' is set correctly in the
options passed into firebase.initializeApp()." bad-subscription
"The subscription must be a valid PushSubscription." bad-token : "The
FCM Token used for storage / lookup was not a valid token string."
bad-vapid-key
"The public VAPID key is not a Uint8Array with 65 bytes."
bg-handler-function-expected
"The input to setBackgroundMessageHandler() must be a function."
delete-scope-not-found
"The deletion attempt for service worker scope could not be performed
as the scope was not found." delete-token-not-found
"The deletion attempt for token could not be performed as the token
was not found." failed-delete-vapid-key
"The VAPID key could not be deleted."
failed-serviceworker-registration
"We are unable to register the default service worker.
{$browserErrorMessage}" failed-to-delete-token
"Unable to delete the currently saved token." get-subscription-failed
"There was an error when trying to get any existing Push
Subscriptions." incorrect-gcm-sender-id
"Please change your web app manifest's 'gcm_sender_id' value to
'103953800507' to use Firebase messaging." invalid-delete-token
"You must pass a valid token into deleteToken(), i.e. the token from
getToken()." invalid-public-vapid-key
"The public VAPID key must be a string." invalid-saved-token
"Unable to access details of the saved token."
no-fcm-token-for-resubscribe
"Could not find an FCM token and as a result, unable to resubscribe.
Will have to resubscribe the user on next visit." no-sw-in-reg
"Even though the service worker registration was successful, there was
a problem accessing the service worker itself."
no-window-client-to-msg
"An attempt was made to message a non-existant window client."
notifications-blocked
"Notifications have been blocked." only-available-in-sw
"This method is available in a service worker context."
only-available-in-window
"This method is available in a Window context." permission-blocked
"The required permissions were not granted and blocked instead."
permission-default
"The required permissions were not granted and dismissed instead."
public-vapid-key-decryption-failed
"The public VAPID key did not equal 65 bytes when decrypted."
should-be-overriden
"This method should be overriden by extended classes."
sw-reg-redundant
"The service worker being used for push was made redundant."
sw-registration-expected
"A service worker registration was the expected input."
token-subscribe-failed
"A problem occured while subscribing the user to FCM: {$message}"
token-subscribe-no-push-set
"FCM returned an invalid response when getting an FCM token."
token-subscribe-no-token
"FCM returned no token when subscribing the user to push."
token-unsubscribe-failed
"A problem occured while unsubscribing the user from FCM: {$message}"
token-update-failed
"A problem occured while updating the user from FCM: {$message}"
token-update-no-token
"FCM returned no token when updating the user to push."
unable-to-resubscribe
"There was an error while re-subscribing the FCM token for push
messaging. Will have to resubscribe the user on next visit.
{$message}" unsupported-browser
"This browser doesn't support the API's required to use the firebase
SDK." use-sw-before-get-token
"You must call useServiceWorker() before calling getToken() to ensure
your service worker is used."
Configure to server to receive notifications
Inside public folder, add the following line to manifest.json:
{
//...manifest properties
"gcm_sender_id": "103953800507" <--- add this line to the file
}
Note: if the project wasn't created using Vue Cli, manually create the manifest.json file. (Thanks #natghi)
firebase-messaging-sw.js
importScripts('https://www.gstatic.com/firebasejs/3.9.0/firebase-app.js');
importScripts('https://www.gstatic.com/firebasejs/3.9.0/firebase-messaging.js');
var config = {
messagingSenderId: <Sender ID>
};
firebase.initializeApp(config);
let messaging = firebase.messaging();
In your main.js file add the following code
var config = {
apiKey: <API_KEY>,
authDomain: <DOMAIN>,
databaseURL: <DATABASE_URL>,
projectId: <PROJECT_ID>,
storageBucket: <STORAGE_BUCKET>,
messagingSenderId: <SENDER_ID>
};
firebase.initializeApp(config);
Vue.prototype.$messaging = firebase.messaging()
navigator.serviceWorker.register('/firebase-messaging-sw.js')
.then((registration) => {
Vue.prototype.$messaging.useServiceWorker(registration)
}).catch(err => {
console.log(err)
})
Receive notifications
Then in your App.vue, add this code to the created() function
created() {
var config = {
apiKey: <API_KEY>,
authDomain: <DOMAIN>,
databaseURL: <DATABASE_URL>,
projectId: <PROJECT_ID>,
storageBucket: <STORAGE_BUCKET>,
messagingSenderId: <SENDER_ID>
};
firebase.initializeApp(config);
const messaging = firebase.messaging();
messaging
.requestPermission()
.then(() => firebase.messaging().getToken())
.then((token) => {
console.log(token) // Receiver Token to use in the notification
})
.catch(function(err) {
console.log("Unable to get permission to notify.", err);
});
messaging.onMessage(function(payload) {
console.log("Message received. ", payload);
// ...
});
}
Send notification
UPDATE
const admin = require("firebase-admin")
var serviceAccount = require("./certificate.json");
admin.initializeApp({
credential: admin.credential.cert(serviceAccount),
});
const Messaging = admin.messaging()
var payload = {
webpush: {
notification: {
title: "Notification title",
body: "Notification info",
icon: 'http://i.imgur.com/image.png',
click_action: "http://yoursite.com/redirectPage"
},
},
topic: "Doente_" + patient.Username
};
return Messaging.send(payload)
Older version
Then, in postman you do the following request
POST /v1/projects/interact-f1032/messages:send HTTP/1.1
Host: fcm.googleapis.com
Authorization: Bearer <SENDER_TOKEN>
Content-Type: application/json
{
"message":{
"token" : The token that was in the console log,
"notification" : {
"body" : "This is an FCM notification message!",
"title" : "FCM Message"
}
}
}
Sender Token
In your backend, use the following code, where the file "certificate.json" was got in the firebase dashboard (https://firebase.google.com/docs/cloud-messaging/js/client - Generate pair of keys)
const {google} = require('googleapis');
function getAccessToken() {
return new Promise(function(resolve, reject) {
var key = require('./certificate.json');
var jwtClient = new google.auth.JWT(
key.client_email,
null,
key.private_key,
["https://www.googleapis.com/auth/firebase",
"https://www.googleapis.com/auth/cloud-platform"],
null
);
jwtClient.authorize(function(err, tokens) {
if (err) {
reject(err);
return;
}
resolve(tokens.access_token);
});
});
}
getAccessToken().then(senderToken => console.log(senderToken))
The senderToken is used on the Authorization header to send a notification

Fire-base web notification not received while no errors

I am working with web app in which I want to integrate Firebase Notifications but after I setup all the requirements I tried to use Firebase notification composer to test it, I got no errors and the status of the message was completed but I received nothing neither on background nor in foreground.
here is my code
index.html
<script src="https://www.gstatic.com/firebasejs/4.10.1/firebase.js"></script>
<script>
// Initialize Firebase
var config = {
apiKey: "MY_API_KEY",
authDomain: "app.firebaseapp.com",
databaseURL: "https://app.firebaseio.com",
projectId: "app",
storageBucket: "app.appspot.com",
messagingSenderId: "MY_SENDER_ID"
};
firebase.initializeApp(config);
var messaging = firebase.messaging();
messaging.usePublicVapidKey("BLWwgk4yFuoNHdPDccuDnXYmhxZA8kwpWArWaE3t7njDT90-30dcWlJIhFbXxMpfXczcvtU8AvMf_F1EJg8Qy");
messaging.requestPermission().then(function(res) {
console.log('test')
messaging.getToken().then(function(res){
console.log(res)
})
})
messaging.onTokenRefresh(function() {
messaging.getToken()
.then(function(refreshedToken) {
console.log('Token refreshed.');
})
.catch(function(err) {
console.log('Unable to retrieve refreshed token ', err);
});
});
messaging.onMessage(function(payload) {
console.log("Message received. ", payload);
// ...
});
</script>
firebase-messaging-sw.js
importScripts('https://www.gstatic.com/firebasejs/4.8.1/firebase-app.js');
importScripts('https://www.gstatic.com/firebasejs/4.8.1/firebase-messaging.js');
firebase.initializeApp({
'messagingSenderId': 'MY_SENDER_ID'
});
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: '/firebase-logo.png'
};
return self.registration.showNotification(notificationTitle,
notificationOptions);
});
status of Firebase notification composer
Notes:
no errors on browser console.
no errors on Firebase console.
i had the same problem then i figured out that the version of firebase im using in the foreground is different than the version in sw, so i changed to the same version i use in the foreground and the problem is solved. Hope this help
I had the exact same problem. The problem was not in my front-end code at all but in the requests sent from firebase console. I would suggest you use Postman or your own backend to send a request to see if it works.
Heres a quick demo of my postman request -
method: POST
url : https://fcm.googleapis.com/fcm/send
Headers :
"Content-Type": "application/json",
"Authorization": (Your server key which is found in Cloud messaging settings in firebase console) Edit: Make sure to add "key=" before your server key. Example - "Authorization" : "key=AAAA7_.......QRIM"
Body:
"to" : (Your front end app token),
"data" : {
"body" : "Test message",
"title" : "Test title"
}
Hope this helps

Resources