Web firebase.messaging().onMessage not fired, but background notification perfectly fired - javascript

I want to reload or trigger some event in foregrounf if push message is sent with firebase.messaging().onMessage, but it not fired. I'm using firebase.mesaging.sw.js with background notification and it works correctly what is wrong with my code?
firebase.js
const config = {
apiKey: "x",
projectId: "x",
storageBucket: "x",
messagingSenderId: "x"
};
firebase.initializeApp(config);
const msg = firebase.messaging()
msg.requestPermission()
.then(() => {
return msg.getToken()
})
.then((token) => {
})
.catch((err) => {
})
msg.onMessage(function(payload) {
alert("Foreground message fired!")
console.log(payload)
});
firebase.messaging.sw.js
importScripts("https://www.gstatic.com/firebasejs/7.0.0/firebase-app.js");
importScripts("https://www.gstatic.com/firebasejs/7.0.0/firebase-messaging.js");
const config = {
apiKey: "x",
projectId: "x",
storageBucket: 'x',
messagingSenderId: "x"
};
firebase.initializeApp(config);
const msg = firebase.messaging()
msg.setBackgroundMessageHandler(function(payload) {
let options = {
body: payload.data.body,
icon: payload.data.icon
}
return self.registration.showNotification(payload.data.title, options);
});
I don't know what is wrong with my code

Simple solution to this is update your Firebse to latest version.
Eg.
importScripts('https://www.gstatic.com/firebasejs/7.8.0/firebase-app.js');
importScripts('https://www.gstatic.com/firebasejs/7.8.0/firebase-messaging.js');
Note: Once you have updated your firebase libraries versions then messagingSenderId will not work in your firebase-messaging-sw.js file. You have to provide all other params eg. apiKey, projectId, appId along with messagingSenderId.
If still not work. Clean your browser cache and re-register service worker.
For more details you can refer to this solution

Still had the same issue in 2020. In my case it was like this:
you need to have same versions in importScripts for background messages and in your app for foreground messages
call it after obtaining token for background service
firebaseApp.messaging().getToken().then((currentToken) => {
if (currentToken) {
console.log(currentToken)
} else {
// Show permission request.
console.log(
'No Instance ID token available. Request permission to generate one.')
}
/** When app is active */
firebase.messaging().onMessage((payload) => {
console.log(payload)
}, e => {
console.log(e)
})
})

For anyone else with this problem, I finally solved it by:
Upgrading the Firebase SDK version in both header-included JS files and the SW JS file to latest (currently, that would be 7.8.1).
Adding the entire firebaseConfig array to the SW firebase.initializeApp(), as the previous answer suggests.
Cleaning the Chrome cache from the Application > Clear Storage section in the Developer Tools.
Deleting the previous registration token from my database.
Blocking and unblocking notifications from the browser to force a new token generation.
Basically, a total fresh start with updated Firebase SDK seems to fix issues like this.

You are missing lots of things and onMessage will only work if firebase is initialized before calling it. Please follow this. I have done it like this and it is working.
initialize firebase and get the token
export class BrowserFcmProvider {
export const FIREBASE_CONFIG = {
apiKey: "****",
authDomain: "****",
databaseURL: "****",
projectId: "****",
storageBucket: "****",
messagingSenderId: "****",
appId: "****"
}
firebase.initializeApp(FIREBASE_CONFIG);
async webGetToken() {
try {
const messaging = firebase.messaging();
await messaging.requestPermission();
const token = await messaging.getToken();
let uuidTemp = new DeviceUUID().get();
return this.saveTokenToFireStoreFromWeb(token, uuidTemp)
} catch (e) {
console.log(e);
}
}
saveTokenToFireStoreFromWeb(token, uuid) {
try {
const docData = {
token: token,
device_type: 'web',
uuid: uuid
}
const devicesRef = this.db.collection('devices')
return devicesRef.doc(uuid).set(docData);
} catch (e) {
console.log(e, 'saveTokenError');
}
}
showMessage() {
try {
const messaging = firebase.messaging();
messaging.onMessage((payload) => {
console.log(payload);
})
} catch (e) {
console.log(e)
}
}
}
And calling the method while app loads like this
async configureFirebaseForBrowser(res) {
await this.bfcm.webGetToken();
this.bfcm.showMessage();
}
Firebase function and payload type
const payloadWeb = {
title: title,
body: body,
data: {
title: title,
body: body
},
tokens: uniqueDevicesTokenArrayWeb,
}
const responseWeb = await admin.messaging().sendMulticast(payloadWeb);
console.log(responseWeb.successCount + ' notifications has been sent to Web successfully');
I have used async and await as we need to manage firebase/firestore operations asynchronously.
fcm does not work in Incognito mode and safari browser

Same issue i was faced. In my case firebase version in "package.json" and "firebase-messaging-sw.js" importScripts version was different. After set same version in "firebase-messaging-sw.js" importScripts which was in
"package.json", my issue is resolved.
Before change
**"package.json"**
"firebase": "^8.2.1",
**"firebase-messaging-sw.js"**
importScripts('https://www.gstatic.com/firebasejs/7.8.0/firebase-app.js');
importScripts('https://www.gstatic.com/firebasejs/7.8.0/firebase-messaging.js');
After change
**"package.json"**
"firebase": "^8.2.1",
**"firebase-messaging-sw.js"**
importScripts('https://www.gstatic.com/firebasejs/8.2.1/firebase-app.js');
importScripts('https://www.gstatic.com/firebasejs/8.2.1/firebase-messaging.js');

Related

How to implement Firebase(FCM) Push Notifications on nuxtjs / vuejs

Having devoted many hours to search the internet for a simple and straightforward way of how to implement Firebase FCM Push Notification on my nuxt project bore no fruit.
Here is how to implement FCM Push Notifications on your NuxtJs/Vuejs project
Step 1
Create your nuxt app like npx create-nuxt-app <your-app-name>
Step 2
Install firebase npm install firebase and #nuxt/firebase npm install #nuxt/firebase
Step 3
Creating your firebase project
Go to firebase console and create a project
Give it a name
Enable Google analytics if you like to then click on create
-Get some coffee as the projects creates ☕
On this page you want to copy the config, which we will use later
Finally, we land on the home page of our project on firebase, looks like below image
Let's go back to our project
Step 4
On your nuxt.config.js add
// Modules: https://go.nuxtjs.dev/config-modules
modules: [
'#nuxtjs/firebase',
],
// firebase FCM starts here
firebase: {
lazy: false,
config: {
apiKey: <apiKey>,
authDomain: <authDomain>,
projected: <projectId>,
storageBucket: <storageBucket>,
messagingSenderId: <messagingSenderId>,
appId: <appId>,
measurementId: <measurementId>,
databaseURL: <databaseURL>,
},
onFirebaseHosting: false,
services: {
messaging: true,
}
},
messaging: {
createServiceWorker: true,
actions: [
{
action: 'goHome',
url: 'https://localhost:3000'
}
],
fcmPublicVapidKey: <vapidKey>
},
To get your vapidKey navigate to Project Settings on your firebase console and select Cloud Messaging, scroll down and press on Generate Key Pair to have your vapidKey.See image below
copy and paste it on your nuxt.config.js
Step 5
On the static folder at your project root create a file named firebase-messaging-sw.js and paste the input the configs as below
importScripts('https://www.gstatic.com/firebasejs/8.2.7/firebase-app.js');
importScripts('https://www.gstatic.com/firebasejs/8.2.7/firebase-messaging.js');
// Initialize the Firebase app in the service worker by passing the generated config
var firebaseConfig = {
apiKey: <apiKey>,
authDomain: <authDomain>,
projected: <projectId>,
storageBucket: <storageBucket>,
messagingSenderId: <messagingSenderId>,
appId: <appId>,
measurementId: <measurementId>,
databaseURL: <databaseURL>,
};
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);
});
Step 6
On your index.vue configure it as follows
<template>
<div>
<h1>Get Notified</h1>
</div>
</template>
<script>
export default {
data() {
return {
listenersStarted: false,
idToken: "",
};
},
mounted() {
this.startListeners();
},
methods: {
// FCM NOTIFICATION FUNCTIONS
async startListeners() {
await this.startOnMessageListener();
await this.startTokenRefreshListener();
await this.requestPermission();
await this.getIdToken();
this.listenersStarted = true;
},
startOnMessageListener() {
try {
this.$fire.messaging.onMessage((payload) => {
console.info("Message received : ", payload);
console.log(payload.notification.body);
});
} catch (e) {
console.error("Error : ", e);
}
},
startTokenRefreshListener() {
try {
this.$fire.messaging.onTokenRefresh(async () => {
try {
await this.$fire.messaging.getToken();
} catch (e) {
console.error("Error : ", e);
}
});
} catch (e) {
console.error("Error : ", e);
}
},
async requestPermission() {
try {
const permission = await Notification.requestPermission();
console.log("GIVEN notify perms");
console.log(permission);
} catch (e) {
console.error("Error : ", e);
}
},
async getIdToken() {
try {
this.idToken = await this.$fire.messaging.getToken();
console.log("TOKEN ID FOR this browser");
console.log(this.idToken);
} catch (e) {
console.error("Error : ", e);
}
},
},
};
</script>
Step 7
Run npm run dev , open your console to see if the permissions to display notifications are granted. Accept if promoted to allow notifications.
Step 8
Navigate to Cloud Messaging on firebase Engage menu and click on Send your first message. Type the content you would like your notification to have and select your app as the target user, there we have it you should see a notification on your browser like so

firebase.database.ref is not a function React Native / Expo

I am pretty new to expo and firebase, and I have this error that I have no idea what the issue is. I am trying to fetch photos from firebase database. I know for sure the issue is not with firebase config because I can upload photos into firebase storage.
I suspect the issue is with exporting and importing firebase.
This is the error message I am getting :
[TypeError: _firebase.db.ref is not a function. (In
'_firebase.db.ref('users/photos')', '_firebase.db.ref' is undefined)]
Note: I am using firebase v9
App.js file:
import { db } from './firebase';
export default function App() {
async function loadPhotos() {
try {
db.ref('users/photos')
.then(url => {
console.log('URL: ', url);
})
.catch(e => console.log(e));
console.log('Got here');
} catch (error) {
console.log('error', error);
}
}
...............
}
firebase.js file:
import firebase from 'firebase/compat/app';
import { getDatabase } from 'firebase/database';
const firebaseConfig = {
apiKey: '......',
authDomain: '.....',
projectId: '....',
storageBucket: '....',
messagingSenderId: '....',
appId: '.....',
measurementId: '....',
};
if (!firebase.apps.length) {
firebase.initializeApp(firebaseConfig);
}
export const db = getDatabase();
In v9 and later of the Firebase SDK, most functionality that was a method on the objects in the past, is now available as a top-level function.
So instead of db.ref('users/photos'), you need to do ref(db, 'users/photos').
You're also missing a get call, which is how you actually retrieve the data from the reference:
get(ref(db, 'users/photos'))
.then(url => {
console.log('URL: ', url);
})
.catch(e => console.log(e));
This is all pretty well documented in the Firebase documentation on reading data, so I recommend keeping that handy. Alternatively you can use the compat paths in v9, to make the older syntax work as shown in the upgrade guide/

db.collection is not a function firebase firestore

Hello I am trying to configure react app with firebase and use firestore.
"firebase": "^9.1.3"
I followed the instructions given in official docs.
Here is my congig.js file.
import { initializeApp } from 'firebase/app';
import { getFirestore } from 'firebase/firestore';
const firebaseConfig = {
apiKey: '****',
authDomain: '*****',
projectId: '*****',
storageBucket: '*****',
messagingSenderId: '****',
appId: '*****',
};
const app = initializeApp(firebaseConfig);
export const db = getFirestore(app);
I am sure this gets initialized.
When I export it and use it in other file. collection is greyed out in vs code that means i am not using the import.
databaseservice.js
import { db } from './config';
import { collection, doc } from 'firebase/firestore';
export const getChapters = (scanId) => {
db.collection('somecollection')
.doc(scanId)
.get()
.then((doc) => {
if (doc.exists) {
console.log('Document data:', doc.data());
} else {
// doc.data() will be undefined in this case
console.log('No such document!');
}
})
.catch((error) => {
console.log('Error getting document:', error);
});
};
Error:TypeError: config__WEBPACK_IMPORTED_MODULE_0_.db.collection is not a function
I have tried with compat and lite versions. Getting the same issue.
This is v8/compat syntax:
db.collection('somecollection')
.doc(scanId)
.get()
.then((doc) => {
In v9/modular syntax, the equivalent is:
getDoc(doc(db, 'somecollection', scanId))
.then((doc) => {
For converting this type of thing, I find it easiest to keep the Firebase documentation and upgrade guide handy.
Firebase have changed their API to new modular syntax in version 9. You are using old syntax from version 8. You can read more about this and find instructions on upgrading your code here: https://firebase.google.com/docs/web/modular-upgrade
Also, everywhere in Firebase documentation, they now have 2 separate examples: one for old syntax, one or new modular syntax: https://firebase.google.com/docs/firestore/query-data/get-data

Firebase: Confusion regarding batched writes

I'm having some difficulties with firebase batched write in my React app.
Using the following async function:
export const addCollectionAndDocuments = async (collectionKey, objectsToAdd) => {
const collectionRef = firestore.collection(collectionKey);
const batch = firestore.batch();
objectsToAdd.forEach(obj => {
const newDocRef = collectionRef.doc();
batch.set(newDocRef, obj);
});
return await batch.commit();
}
If I call the function in my app in a way similar to this:
var list = [
{ date: '12/1/2011', reading: 3, id: 20055 },
{ date: '13/1/2011', reading: 5, id: 20053 },
{ date: '14/1/2011', reading: 6, id: 45652 }
];
addCollectionAndDocuments('foo-collection', list)
.then((value) => {
console.log('then ' + value);
})
.catch((e) => {
console.log('catch', e);
})
.finally(() => {
console.log('finally');
});
This doesn't do anything, unless I modify/invalidate my firebase API key in my firebase config object (i.e., in my app, modify the API key so that it doesn't correspond to my actual firebase API key) and then run the code. In that case, it works just fine, which puzzles me.
I am initializing firebase in a way similar to this:
import firebase from 'firebase/app';
import 'firebase/firestore';
import 'firebase/auth';
const config = {
apiKey: "xxxxxx",
authDomain: "xxxxxx",
databaseURL: "xxxxxx",
projectId: "xxxxxx",
storageBucket: "xxxxxx",
messagingSenderId: "xxxxxx",
appId: "xxxxxx"
};
firebase.initializeApp(config);
I have tried this numerous times, but nothing happens until I invalidate my firebase API key. Until then, I don't even reach any of the 'then', 'catch' nor the 'finally' methods in my promise.
The code above is in a simple create-react-app and I am currently running it on the 'react-scripts start' development server.
If I instead run batched write code in a static html document, it works completely as expected:
<!DOCTYPE html>
<html>
<body>
<script src="https://www.gstatic.com/firebasejs/3.7.4/firebase.js"></script>
<script src="https://www.gstatic.com/firebasejs/7.2.2/firebase-firestore.js"></script>
<script>
// Initialize Firebase
var config = {
apiKey: "x",
authDomain: "x",
databaseURL: "x",
projectId: "x",
storageBucket: "x",
messagingSenderId: "x",
appId: "x"
};
firebase.initializeApp(config);
function myFunction() {
// Get a new write batch
const firestore = firebase.firestore();
var batch = firestore.batch();
// Set the value of 'NYC'
var nycRef = firestore.collection("cities").doc("NYC");
batch.set(nycRef, {name: "New York City"});
// Commit the batch
batch.commit().then(() => {
console.log('done');
});
}
</script>
<p>run stuff</p>
<button onclick="myFunction()">Run batched write</button>
</body>
</html>
Any idea what this is about?
Thanks

Firebase cloud message/notifications are not receiving. JS

I am trying to send FCM to my react app using cloud functions.
Cloud function is executing, but notification is not being received on client side.
Here cloud function code.
exports.sendPush = functions.database.ref('/settings2').onWrite(event => {
let projectStateChanged = false;
let projectCreated = false;
let projectData = event.data.val();
if (!event.data.previous.exists()) {
projectCreated = true;
}
if (!projectCreated && event.data.changed()) {
projectStateChanged = true;
}
let msg = 'A project state was changed';
if (projectCreated) {
msg = `The following new project was added to the project: ${projectData.title}`;
}
tokens.push("fIGxxxxGtDGxxxx DEVICE Token");
let payload = {
notification: {
title: 'Firebase Notification',
body: 'This Is Message',
sound: 'default',
badge: '1'
}
};
return admin.messaging().sendToDevice(tokens, payload);
});
Here is the log of Cloud function
And here is code on my client side:
messaging.onMessage(function(payload) {
console.log("Message received. ", payload);
// ...
});
There are not any errors, but nothing is in console. Do I have to do something with service worker file?
Any help would be appreciated.
There was an issue with my firebase-messaging-sw.js file. I have resolved this by following code.
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 = {
apiKey: "AIzaSyDtg4aQMQW67Jla1nUzrTTSEhVqpUeqKXI",
authDomain: "payxxxxxxx.firebaseapp.com",
databaseURL: "https://pxyxxxxx.firebaseio.com",
projectId: "pxxoll-pxxxs-fxxx",
storageBucket: "pxxx-pxxx-fxxxx1.apxxxot.com",
messagingSenderId: "2xxxx5xxx"
};
firebase.initializeApp(config);
const messaging = firebase.messaging();
For anyone new that may run across this post and are having issues with this especially if you copied and pasted something from online make sure you check the importScripts version and make sure its the same version as in your package.json file.
Example
Currently this package version is 8.3.1
so update
importScripts('https://www.gstatic.com/firebasejs/3.9.0/firebase-app.js');
importScripts('https://www.gstatic.com/firebasejs/3.9.0/firebase-messaging.js');
to
importScripts('https://www.gstatic.com/firebasejs/8.3.1/firebase-app.js');
importScripts('https://www.gstatic.com/firebasejs/8.3.1/firebase-messaging.js');

Categories

Resources