PWA foreground push notifications - javascript

i have a problem with foreground push notifications.
I just want to get the data in the console for the moment but it didn't work. I follow the guide on firebase documentation but this function is never triggered...
messaging.onMessage((payload) => {
console.log('Message received. ', payload);
});
Background notifications works as expected.
Here is my VueJs file
import * as firebase from "firebase/app";
import 'firebase/messaging';
const config = {
apiKey: "",
authDomain: "",
databaseURL: "",
projectId: "",
storageBucket: "",
messagingSenderId: "",
appId: ""
};
firebase.initializeApp(config);
const messaging = firebase.messaging();
messaging.usePublicVapidKey("");
export default {
name: 'App',
mounted() {
messaging.onMessage((payload) => { // Don't work here
console.log('Message received. ', payload);
});
this.getMsgPushToken();
},
methods: {
...mapMutations('auth', ['mutMsgPushToken']),
getMsgPushToken() {
let that = this
messaging.requestPermission().then(async function() {
messaging.getToken().then((token) => {
that.mutMsgPushToken(token); // Where i get the FCM token
})
}).catch((err) => {
console.log('Unable to get permission to notify.', err);
});
},
},
};
And my service worker
importScripts('https://www.gstatic.com/firebasejs/5.5.6/firebase-app.js');
importScripts('https://www.gstatic.com/firebasejs/5.5.6/firebase-messaging.js');
firebase.initializeApp({
'messagingSenderId': ''
});
const messaging = firebase.messaging();
If you have any idea of what i'm missing, i would love to hear it ha ha

Related

Reference error: self is not defined when implementing firebase messaging

In my Nextjs project I'm trying to implement push notification with firebase messaging (my firebase version is 8.10.0), after creating the firebase-messaging-sw.js file in my public folder:
importScripts(
"https://www.gstatic.com/firebasejs/8.10.0/firebase-app.js"
);
importScripts(
"https://www.gstatic.com/firebasejs/8.10.0/firebase-messaging.js"
);
const firebaseConfig = {
apiKey: "***",
authDomain: "***",
projectId: "***",
storageBucket: "***",
messagingSenderId: "***",
appId: "***",
measurementId: "***"
};
firebase.initializeApp(firebaseConfig)
const messaging = firebase.messaging();
messaging.onBackgroundMessage((payload) => {
const notificationTitle = payload.notification.title;
const notificationOptions = {
body: payload.notification.body,
icon: null,
};
self.registration.showNotification(notificationTitle, notificationOptions);
});
I now created a [utility] file (that I named Firebase.js) where I'll implement helper functions like the request token function.
Here is a code snippet from that file:
import firebase from "firebase/app";
import "firebase/messaging";
const firebaseConfig = {
apiKey: "***",
authDomain: "***",
projectId: "***",
storageBucket: "***",
messagingSenderId: "***",
appId: "***",
measurementId: "***"
};
!firebase.apps.length && firebase.initializeApp(firebaseConfig);
const messaging = firebase.messaging();
export const requestForToken = () => {
// func that generates and returns a FCM token
};
export const onMessageListener = async () =>
new Promise((resolve) => {
messaging.onMessage((payload) => {
resolve(payload);
}
);
});
Now to use those functions I created another file Notification.js:
import React, { useState, useEffect } from "react";
import { toast } from "react-toastify";
import { requestForToken, onMessageListener } from "./Firebase";
const Notification = () => {
const [notification, setNotification] = useState({ title: "", body: "" });
useEffect(() => {
requestForToken();
}, []);
const ToastDisplay = () => {
return (
<>
<b>{notification?.title} </b>
<p>{notification?.body}</p>
</>
);
};
const notify = () => toast(<ToastDisplay />);
useEffect(() => {
notification?.title && notify();
}, [notification]);
onMessageListener()
.then((payload) => {
setNotification({
title: payload?.notification?.title,
body: payload?.notification?.body,
});
})
.catch((err) => console.log("failed: ", err));
return <></>;
};
export default Notification;
I imported Notification.js in _app.js and when I run my app I get the following error:
And I can't understand the reason why and [more importantly] how to fix it.
Hope this should work as All the setup I have worked inclined with your requirement,
Here are version's those I am using,
"next": "^12.0.7",
"firebase": "^8.6.8",
"#firebase/installations": "^0.5.4"
Here is firebase init'n,
/* eslint-disable import/prefer-default-export */
// import firebase from 'firebase/app';
import firebaseClient from "firebase/app";
import "firebase/installations";
import "firebase/auth";
import "firebase/messaging";
import "firebase/functions";
import "firebase/analytics";
const CLIENT_CONFIG = {
apiKey: "***",
authDomain: "***",
databaseURL: "***",
projectId: "***",
storageBucket: "***",
messagingSenderId: "***",
appId: "***",
measurementId: "***",
};
if (typeof window !== "undefined" && firebaseClient.apps?.length <= 0) {
firebaseClient.initializeApp(CLIENT_CONFIG);
(window as any).firebase = firebaseClient;
if (firebaseClient.messaging.isSupported()) {
const msg = firebaseClient.messaging();
const creds = {
vapidKey: process.env.NEXT_PUBLIC_FIREBASE_WEB_FCM_TOKEN
? process.env.NEXT_PUBLIC_FIREBASE_WEB_FCM_TOKEN
: "",
};
msg.getToken(
creds,
)
.then((token) => {
// Send the token to your app server if notification service granted
console.log(token);
})
.catch((err) => {
// If user blocks notification service
console.log(err);
});
}
}
export { firebaseClient };
Here is the firebase-messaging-sw.js at public folder
/* eslint-disable space-before-function-paren */
if ("serviceWorker" in navigator) {
navigator.serviceWorker
.register("../firebase-messaging-sw.js")
.then((registration) => {
console.log("Registration successful, scope is:", registration.scope);
})
.catch((err) => {
console.log("Service worker registration failed, error:", err);
});
}
Hope this get your working!.
Try this:
import { initializeApp } from "firebase/app";
import { getMessaging, onMessage } from "firebase/messaging";
const firebaseConfig = {
// ...
};
const app = initializeApp(firebaseConfig);
const messaging = getMessaging(app);
onMessage(messaging, (payload) => {
console.log('Message received. ', payload);
// ...
})
// ...
Also take a look into firebase docs
EDIT:
Take a look here too. It's showing how to receive messages into client.
Hope I've helped you with something :)

Next Js cant find Service messaging (firebase-cloud-messaging)

Hi I using firebase cloud messaging in next js project and when I try to run or build my project I get this error :
info - Checking validity of types
info - Creating an optimized production build
info - Compiled successfully
info - Collecting page data ...node:internal/process/promises:246
triggerUncaughtException(err, true /* fromPromise */);
^
Error: Service messaging is not available
at Provider.getImmediate (file:///I:/Work/Web/Php/Project/wamp/www/test/node_modules/#firebase/component/dist/esm/index.esm2017.js:147:23)
at getMessagingInWindow (I:\Work\Web\Php\Project\wamp\www\test\node_modules#firebase\messaging\dist\index.cjs.js:1460:74)
at I:\Work\Web\Php\Project\wamp\www\test.next\server\pages_app.js:117:83 {
type: 'Error'
}
my code :
it seems this problem happens because using getMessaging
firbase.js
import { initializeApp } from 'firebase/app';
import { getMessaging, getToken, onMessage } from "firebase/messaging";
var firebaseConfig = {
apiKey: "----",
authDomain: "---",
projectId: "---",
storageBucket: "---",
messagingSenderId: "---",
appId: "---",
measurementId: "---"
};
const firebaseApp = initializeApp(firebaseConfig);
const messaging = getMessaging(firebaseApp);
export const fetchToken = (setTokenFound) => {
return getToken(messaging, {vapidKey: '---'}).then((currentToken) => {
if (currentToken) {
console.log('current token for client: ', currentToken);
setTokenFound(true);
// Track the token -> client mapping, by sending to backend server
// show on the UI that permission is secured
} else {
console.log('No registration token available. Request permission to generate one.');
setTokenFound(false);
// shows on the UI that permission is required
}
}).catch((err) => {
console.log('An error occurred while retrieving token. ', err);
// catch error while creating client token
});
}
export const onMessageListener = () =>
new Promise((resolve) => {
onMessage(messaging, (payload) => {
resolve(payload);
});
});
firebase-messaging-sw.js
// Scripts for firebase and firebase messaging
importScripts('https://www.gstatic.com/firebasejs/9.6.11/firebase-app-compat.js');
importScripts('https://www.gstatic.com/firebasejs/9.6.11/firebase-messaging-compat.js');
// Initialize the Firebase app in the service worker by passing the generated config
const firebaseConfig = {
apiKey: "----",
authDomain: "---",
projectId: "---",
storageBucket: "---",
messagingSenderId: "---",
appId: "---",
measurementId: "---"
};
firebase.initializeApp(firebaseConfig);
// Retrieve firebase messaging
const messaging = firebase.messaging();
messaging.onBackgroundMessage(function(payload) {
console.log('Received background message ', payload);
const notificationTitle = payload.notification.title;
const notificationOptions = {
body: payload.notification.body,
};
self.registration.showNotification(notificationTitle,
notificationOptions);
});
_app.tsx
import {fetchToken,onMessageListener} from '../tools/firebase'
const [notification, setNotification] = useState({title: '', body: ''});
const [isTokenFound, setTokenFound] = useState(false);
useEffect(() => {
fetchToken(setTokenFound)
onMessageListener().then(payload => {
setNotification({title: payload.notification.title, body: payload.notification.body})
console.log(payload);
}).catch(err => console.log('failed: ', err));
}, []);
i had same issue turns out it was firebase v9 issue
using firebase v8 worked for me
npm i firebase#8.2.3
after installing v8 don't forget to change syntax its firebase.initializeApp(firebaseConfig);

Unable to change notification title in Firebase Cloud Messaging

I am now able to implement push notifications with Firebase Cloud Messaging, and the push notifications themselves are delivered, but I am having trouble changing their content.
The default title is "This site has been updated in the background", but I changed it to any text.
Environment
Vue CLI
TypeScript
main.ts
import { createApp } from 'vue'
import App from './App.vue'
import router from './router'
import store from './store'
import './registerServiceWorker'
import firebase from 'firebase/compat/app';
import { getMessaging, getToken } from "firebase/messaging";
const firebaseConfig = {
apiKey: "xxx",
authDomain: "xxx",
projectId: "xxx",
storageBucket: "xxx",
messagingSenderId: "xxx",
appId: "xxx",
measurementId: "xxx"
};
const firebaseApp = firebase.initializeApp(firebaseConfig);
const app = createApp(App)
installElementPlus(app)
app
.use(store)
.use(router)
.component('MqResponsive', Vue3Mq.MqResponsive)
.mount('#app')
const messaging = getMessaging(firebaseApp);
const vapidKey = {
vapidKey:
"xxx",
};
// Messaging
getToken(messaging, { vapidKey: 'xxx' }).then((currentToken) => {
if (currentToken) {
// Send the token to your server and update the UI if necessary
console.log("currentToken : ", currentToken);
// ...
} else {
// Show permission request UI
console.log('No registration token available. Request permission to generate one.');
// ...
}
}).catch((err) => {
console.log('An error occurred while retrieving token. ', err);
// ...
});
firebase-messaging-sw.js
import firebase from 'firebase/compat/app';
import { onBackgroundMessage } from "firebase/messaging/sw";
import { getMessaging, getToken, onMessage } from "firebase/messaging";
const firebaseConfig = {
apiKey: "xxx",
authDomain: "xxx",
projectId: "xxx",
storageBucket: "xxx",
messagingSenderId: "xxx",
appId: "xxx",
measurementId: "xxx"
};
const firebaseApp = firebase.initializeApp(firebaseConfig);
const messaging = getMessaging(firebaseApp);
const vapidKey = {
vapidKey:
"xxx",
};
// Messaging
getToken(messaging, { vapidKey: 'xxx' }).then((currentToken) => {
if (currentToken) {
// Send the token to your server and update the UI if necessary
console.log("currentToken : ", currentToken);
// ...
} else {
// Show permission request UI
console.log('No registration token available. Request permission to generate one.');
// ...
}
}).catch((err) => {
console.log('An error occurred while retrieving token. ', err);
// ...
});
onMessage(messaging, (payload) => {
console.log('Message received. ', payload);
// ...
});
onBackgroundMessage(messaging, (payload) => {
console.log('[firebase-messaging-sw.js] Received background message ', payload);
self.addEventListener('push', async function (event) {
event.waitUntil(
self.registration.showNotification('title', {
body: 'body'
})
);
});
});
The image is localhost, but deploying to the web did not change the result.
I also tested on Firebase Messaging and downloaded as a PWA and again the results did not change.
What is the problem??
Thank you in advance!

How to integrate PWA with Next.js to allow for notifications and push notifications

I'm building a PWA with next.js and have been having a few issues.
I am trying to integrate in device motion to my users accounts and geolocation, and then notifications.
Basing this off of this repo, https://github.com/shadowwalker/next-pwa/ , and this tutorial, https://medium.com/#sarafathulla/how-to-add-firebase-push-notifications-in-next-js-react-8eecc56b5cab .
As well as these API's, https://whatwebcando.today/device-motion.html and https://whatwebcando.today/geolocation.html .
Currently the PWA is boilerplate using next-pwa,
next.config.js
module.exports = withPWA({
pwa: {
disable: process.env.NODE_ENV === 'development',
dest: 'public',
runtimeCaching,
},
poweredByHeader: false,
},
withBundleAnalyzer(),
)
I am very confused about how one can integrate just the simple device motion into the PWA, and how to move forward in general.
If someone could point me in the right direction that would be brilliant! So different from usual web dev code.
this working for me
// public/firebase-messaging-sw.js
importScripts('https://www.gstatic.com/firebasejs/7.9.1/firebase-app.js');
importScripts('https://www.gstatic.com/firebasejs/7.9.1/firebase-messaging.js');
firebase.initializeApp({
apiKey: '****',
authDomain: '*****',
projectId: '*****',
storageBucket: '******',
messagingSenderId: '*****',
appId: '*****',
measurementId: '*****',
});
firebase.messaging();
//background notifications will be received here
firebase.messaging().setBackgroundMessageHandler((payload) => {
const { title, body } = JSON.parse(payload.data.notification);
var options = {
body,
icon: '/icons/launcher-icon-4x.png',
};
registration.showNotification(title, options);
});
// webpush.js
import 'firebase/messaging';
import firebase from 'firebase/app';
import localforage from 'localforage';
const firebaseCloudMessaging = {
//checking whether token is available in indexed DB
tokenInlocalforage: async () => {
return localforage.getItem('fcm_token');
},
//initializing firebase app
init: async function () {
if (!firebase.apps.length) {
firebase.initializeApp({
apiKey: '****',
authDomain: '*****',
projectId: '*******',
storageBucket: '******',
messagingSenderId: '******',
appId: '*****',
measurementId: '*******',
});
try {
const messaging = firebase.messaging();
const tokenInLocalForage = await this.tokenInlocalforage();
//if FCM token is already there just return the token
if (tokenInLocalForage !== null) {
return tokenInLocalForage;
}
//requesting notification permission from browser
const status = await Notification.requestPermission();
if (status && status === 'granted') {
//getting token from FCM
const fcm_token = await messaging.getToken();
if (fcm_token) {
//setting FCM token in indexed db using localforage
localforage.setItem('fcm_token', fcm_token);
//return the FCM token after saving it
return fcm_token;
}
}
} catch (error) {
console.error(error);
return null;
}
}
},
};
export { firebaseCloudMessaging };
// _app.js
import { firebaseCloudMessaging } from '../webPush';
import firebase from 'firebase/app';
useEffect(() => {
setToken();
async function setToken() {
try {
const token = await firebaseCloudMessaging.init();
if (token) {
getMessage();
}
} catch (error) {
console.log(error);
}
}
function getMessage() {
const messaging = firebase.messaging();
console.log({ messaging });
messaging.onMessage((message) => {
const { title, body } = JSON.parse(message.data.notification);
var options = {
body,
};
self.registration.showNotification(title, options);
});
}
});

FCM WEB receive only data and hide notification section or Disable

I am trying to send data form my server to FCM, so that it can be shown on a specific section of my web page. It's like a stock application for example, where the data is constantly updated. In the same way am trying to achieve. So far I have configured it to receive data from FCM and it is being received. But the problem is that it shows the notification to like. My colleague are working on the same there is a option to send only data to the android app and hide notifications to be shown. Likewise I want to do it hear on web, but am unable to do it.
(function () {
// Initialize Firebase
var config = {
apiKey: "xxxxxxxxxxxxxx",
authDomain: "test-xxxxxxxx.xxxxxxxx.com",
databaseURL: "https://xxxxxx-xxxxxxxx.firebaseio.com",
projectId: "xxx-469e9",
storageBucket: "",
messagingSenderId: "xxxxxx"
};
firebase.initializeApp(config);
// Retrieve Firebase Messaging object.
const messaging = firebase.messaging();
messaging.requestPermission()
.then(function() {
console.log('Notification permission granted.');
return messaging.getToken();
})
.then(function(token) {
console.log(token);
})
.catch(function(err) {
console.log('Unable to get permission to notify.', err);
})
messaging.onMessage(function(payload) {
console.log("Message received. ", payload);
// ...
});
}());
on firebase-messaging-sw.js
importScripts('https://www.gstatic.com/firebasejs/4.3.1/firebase-app.js');
importScripts('https://www.gstatic.com/firebasejs/4.3.1/firebase-messaging.js');
// Initialize Firebase
var config = {
apiKey: "xxxxxx",
authDomain: "xxxx-xxxxxxxxxx.com",
databaseURL: "https://xxx-xxx.firebaseio.com",
projectId: "xxxx-xxxxxxxxxx",
storageBucket: "",
messagingSenderId: "xxxxxxxxxxxx"
};
firebase.initializeApp(config);
const messaging = firebase.messaging();
A hack would be to close the notification just after...
messaging.setBackgroundMessageHandler(function (payload) {
var realPush = true;
if(realPush)
{
const notificationOptions = {
body: "It is a REAL push",
data:"true"
};
//We display the notification
return self.registration.showNotification(title, notificationOptions);
}else
{
const notificationOptions = {
body: "It is a SILENT push",
data:"false"
};
//We display a fake notification
return self.registration.showNotification('To delete',notificationOptions).then(function () {
self.registration.getNotifications().then(notifications => {
console.log(notifications);
for (var i =0;i<notifications.length;i++)
{
if(notifications[i].data != "true")
{
//then we destroy the fake notification immedialtely !
notifications[i].close();
}
}
})
});
}
});
The realPush parameter is of course managed by yourself

Categories