So I'm using VueJS with the PWA option enabled. When using Firebase Cloud Messaging (for web app), I'm getting a notification saying: This site has been updated in the background but Only when the tab is not focused or open. If the tab is active, I don't receive anything in the console.
I'm using Postman to send notifications for now, and it returns success
{
"multicast_id": 5364665067527599460,
"success": 1,
"failure": 0,
"canonical_ids": 0,
"results": [
{
"message_id": "0:1550148053476716%2fd9afcdf9fd7ecd"
}
]
}
Here is my main.js
const config = {
apiKey: "API_KEY",
authDomain: "AUTH_DOMAIN",
databaseURL: "DATABASE_URL",
projectId: "PROJECT_ID",
storageBucket: "STORAGE_BUCKET",
messagingSenderId: "SENDER_ID"
};
firebase.initializeApp(config);
const messaging = firebase.messaging();
messaging.usePublicVapidKey("PUBLIC_VAPID_KEY");
navigator.serviceWorker.register('./firebase-messaging-sw.js')
.then((registration) => {
console.log("Now using registration: " + registration);
messaging.useServiceWorker(registration);
}).catch(err => {
console.log("Error in registration");
console.log(err)
});
My firebase-messaging-sw.js (I never saw the console log thats inside setBackgroundMessageHandler)
importScripts('https://www.gstatic.com/firebasejs/5.8.2/firebase-app.js');
importScripts('https://www.gstatic.com/firebasejs/5.8.2/firebase-messaging.js');
var config = {
messagingSenderId: 'SENDER_ID'
};
firebase.initializeApp(config);
let messaging = firebase.messaging();
messaging.setBackgroundMessageHandler(function(payload) {
console.log('[firebase-messaging-sw.js] Received background message ', payload);
return self.registration.showNotification('title', {body: 'message'});
});
And in my App.vue (neither have I ever seen the console log in onMessage)
created() {
this.$messaging.onMessage(function(payload) {
console.log('Message received: ', payload);
// ...
});
},
methods: {
sendNotif() {
this.$messaging.requestPermission().then(() => this.$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);
});
},
},
I can access the token, none of my configuration is wrong or else the postman request wouldn't give success. I've checked out several other questions related to this but no success so far...
Related
I am using #nuxtjs/firebase in a nuxt project. The messaging works, I can send messages from postman via fcm to my website. I can't see any documentation on how I can access the subscribeToTopic.
In my nuxt.config.js I have:
[
'#nuxtjs/firebase',
{
config: {
apiKey: "myapiKey",
authDomain: "myDomain",
projectId: "myProjectId",
storageBucket: "myStorageBucker",
messagingSenderId: "mySenderId",
appId: "myAppId",
measurementId: "myMeasurementId"
},
services: {
auth: {
persistence: 'local',
initialize: {
onAuthStateChangedAction: 'onAuthStateChangedAction',
subscribeManually: false
},
ssr: false
},
messaging: {
createServiceWorker: true,
fcmPublicVapidKey: 'myVapidKey',
inject: fs.readFileSync('./serviceWorker.js')
},
firestore: true
}
}
]
serviceWorker.js has:
self.addEventListener('push', function (e) {
const data = e.data.json();
const options = {
body: data.notification.body,
icon: data.notification.icon,
vibrate: [100, 50, 100],
data: {
dateOfArrival: Date.now(),
primaryKey: '2'
},
};
})
In async mounted I have:
const currentToken = await this.$fire.messaging.getToken()
console.log("token", currentToken)
this.$fire.messaging.onMessage((payload) => {
console.info('Message received. ', payload)
this.$toast.success(payload.data.text + "</br>" + payload.data.additionalInfo, { icon: payload.data.icon });
})
this.$fire.messaging.onTokenRefresh(async () => {
const refreshToken = await this.$fire.messaging.getToken()
console.log('Token Refreshed', refreshToken)
})
This all works as expected.
Apparently I should be able to subscribe to topics, in firebase something like the following can be used:
FirebaseMessaging.getInstance().subscribeToTopic("all")
.addOnCompleteListener { task ->
if (task.isSuccessful) {
//Successfully Subscribed to Notification Service
}else{
//Subscription Notification Service failed
}
}
But, I cannot see how to do that using #nuxtjs/firebase module.
There is no client-side API in the JavaScript SDK to subscribe to a topic. You'll instead need to use a (server-side) Admin SDK to accomplish this.
For example, the subscribeToTopic method you refer to exists in the Node.js SDK and in the Java SDK, but not in the JavaScript/Web or Android SDKs.
I recommend studying the documentation on subscribing a web client to a topic a bit further.
Once you subscribe a client to a topic from the server, the existing client-side code you already have should start receiving messages to that topic too.
I am looking to anonymously connect to a Firestore and grab some data from a collection. This works perfectly fine under javascript, while it fails ("FirebaseError: Missing or insufficient permissions") under node.js. Any pointers will be appreciated.
This is the code that works without a hitch under javascript (I have omited the 'script' includes) and it returns data as expected:
var config = {
apiKey: "xxx",
authDomain: "xxx.firebaseio.com",
projectId: "xxx",
storageBucket: "xxx.appspot.com",
};
firebase.initializeApp(config);
firebase.auth().signInAnonymously().catch(function(error) {
var errorCode = error.code;
var errorMessage = error.message;
console.log(error.message);
});
foo();
async function foo() {
var db=firebase.firestore();
var query = await db.collection("collection").limit(5).get();
query.forEach(function(doc) {
console.log(doc.data());
});
}
This is the code that does not work under node.js. The config/authdata is exactly the same as in the js example above. (It uses the firebase (client) library. My understanding is that the firebase-admin library does not allow anonymous signin.)
const firebase=require('firebase');
var config = {
apiKey: "xxx",
authDomain: "xxx.firebaseio.com",
projectId: "xxx",
storageBucket: "xxx.appspot.com",
};
firebase.initializeApp(config);
firebase.auth().signInAnonymously().catch(function(error) {
var errorCode = error.code;
var errorMessage = error.message;
console.log(error.message);
});
let db = firebase.firestore();
db.collection('collection').get()
.then((snapshot) => {
snapshot.forEach((doc) => {
console.log(doc.id, '=>', doc.data());
});
})
.catch((err) => {
console.log('Error getting documents', err);
});
The following error is triggered when db.collection('collection').get() is called. (earlier anonymous signing goes through)
Error getting documents { FirebaseError: Missing or insufficient permissions.
at new FirestoreError (/root/node_modules/#firebase/firestore/dist/index.node.cjs.js:1201:28)
at JsonProtoSerializer.fromRpcStatus (/root/node_modules/#firebase/firestore/dist/index.node.cjs.js:19708:16)
at JsonProtoSerializer.fromWatchChange (/root/node_modules/#firebase/firestore/dist/index.node.cjs.js:19955:44)
at PersistentListenStream.onMessage (/root/node_modules/#firebase/firestore/dist/index.node.cjs.js:16828:43)
at /root/node_modules/#firebase/firestore/dist/index.node.cjs.js:16757:30
at /root/node_modules/#firebase/firestore/dist/index.node.cjs.js:16797:28
at /root/node_modules/#firebase/firestore/dist/index.node.cjs.js:17844:20
at process._tickCallback (internal/process/next_tick.js:68:7)
code: 'permission-denied',
name: 'FirebaseError',
toString: [Function] }
Thanks again for any pointers!
One possibility is that you are actually not signed-in when you fetch Firestore. As a matter of fact the signInAnonymously() method is asynchronous and you don't wait that the Promise returned by this method resolves before fetching Firestore.
So, the following may solve your problem:
firebase.initializeApp(config);
let db = firebase.firestore();
firebase.auth().signInAnonymously()
.then(cred => {
return db.collection('collection').get()
})
.then((snapshot) => {
snapshot.forEach((doc) => {
console.log(doc.id, '=>', doc.data());
});
})
.catch((err) => {
console.log(err);
});
Note that you should do the same in the JavaScript SDK version:
firebase.auth().signInAnonymously()
.then(cred => {
foo();
}}
.catch(function(error) {
var errorCode = error.code;
var errorMessage = error.message;
console.log(error.message);
});
I'm trying a basic proof of concept with firebase cloud messaging and I'm having pain receiving messages, nothing happens when I send messages even if the app is in foreground, the onMessage event doesn't return anything despite I don't have any error on sending all seem to be ok from postman or fcm console.
I noticed also that chrome://gcm-internals/ displays state "CONNECTING"
here is my app.js but for me it seems more to be related to the gcm state who should display "CONNECTED"
var firebase = require("firebase/app");
require('firebase/messaging');
// Your web app's Firebase configuration
var firebaseConfig = {
apiKey: "AIzaSyCbrs6uvQQ5s6kAp6YfvDzsds_CfMt3-hA",
authDomain: "test-flarum-fcm.firebaseapp.com",
databaseURL: "https://test-flarum-fcm.firebaseio.com",
projectId: "test-flarum-fcm",
storageBucket: "",
messagingSenderId: "977636469573",
appId: "1:977636469573:web:76e2e191f02f8923df6c2c"
};
// Initialize Firebase
var app = firebase.initializeApp(firebaseConfig);
// Retrieve Firebase Messaging object.
var messaging = firebase.messaging();
//console.log(messaging);
console.log('myToken : '+getToken());
Notification.requestPermission().then((permission) => {
if (permission === 'granted') {
console.log('Notification permission granted.');
//getMyToken();
if(isTokenSentToServer()){
console.log("token already saved")
}else{
// TODO(developer): Retrieve an Instance ID token for use with FCM.
getMyToken();
}
} else {
console.log('Unable to get permission to notify.');
setTokenSentToServer(false);
}
});
// Get Instance ID token. Initially this makes a network call, once retrieved
// subsequent calls to getToken will return from cache.
function getMyToken() {
messaging.getToken().then((currentToken) => {
if (currentToken) {
console.log(currentToken);
//sendTokenToServer(currentToken);//#todo
//updateUIForPushEnabled(currentToken);
saveToken(currentToken);
setTokenSentToServer(true);
} else {
// Show permission request.
console.log('No Instance ID token available. Request permission to generate one.');
// Show permission UI.
//updateUIForPushPermissionRequired();//#todo
//setTokenSentToServer(false); //#todo
setTokenSentToServer(false);
}
}).catch((err) => {
console.log('An error occurred while retrieving token. ', err);
//showToken('Error retrieving Instance ID token. ', err);
setTokenSentToServer(false);
});
}
// Callback fired if Instance ID token is updated.
messaging.onTokenRefresh(() => {
messaging.getToken().then((refreshedToken) => {
console.log('Token refreshed.');
// Indicate that the new Instance ID token has not yet been sent to the
// app server.
setTokenSentToServer(false);
// Send Instance ID token to app server.
//sendTokenToServer(refreshedToken);
// ...
}).catch((err) => {
console.log('Unable to retrieve refreshed token ', err);
//showToken('Unable to retrieve refreshed token ', err);
});
});
function setTokenSentToServer(sent) {
window.localStorage.setItem('sentTokenToServer', sent ? 1 : 0);
}
function isTokenSentToServer(){
return window.localStorage.getItem('sentTokenToServer') == 1;
}
function saveToken(token){
myToken = token;
window.localStorage.setItem('myToken', token);
}
function getToken(){
return window.localStorage.getItem('myToken');
}
messaging.onMessage((payload) => {
console.log('Message received. ', payload);
// ...
});
Thanks for your help
[update] I solved the problem of gcm state but that's not wworking better despite the send result seems to be ok in postman
{
"multicast_id": 7270949329343339591,
"success": 1,
"failure": 0,
"canonical_ids": 0,
"results": [
{
"message_id": "0:1569712574121124%e609af1cf9fd7ecd"
}
]
}
I'm trying to implement web push notifications with FireBase. It works good in desktop chrome/firefox, but when it comes to android I can't get the notification token - the promise, returned from messaging.getToken is never resolved, neither throws an error (always pending). I have a service worker, and it is active and running. Here is my code - what do I do wrong?
<script src="https://www.gstatic.com/firebasejs/5.4.2/firebase-app.js"></script>
<script src="https://www.gstatic.com/firebasejs/5.4.2/firebase-messaging.js"></script>
<script>
var config = {
apiKey: "AIzaSyBuFGsjFDCILwYVzLHWLvoRIHSoDZIQBl8",
authDomain: "mobilepush-fd2d5.firebaseapp.com",
databaseURL: "https://mobilepush-fd2d5.firebaseio.com",
projectId: "mobilepush-fd2d5",
storageBucket: "mobilepush-fd2d5.appspot.com",
messagingSenderId: "106871298920"
};
firebase.initializeApp(config);
const messaging = firebase.messaging();
messaging.usePublicVapidKey("BBYGyuGH2KqQSHyc55Di5IQnHc52fY6gqmExfWtg85-wabmQimja6X6ViR2jmNgPBZBuLeX0BXf9A0yLqUV5m90");
var curStatus = messaging.getNotificationPermission_();
if (curStatus == 'granted') {
messaging.getToken().then(function(currentToken) {
if (currentToken) {
processToken(currentToken, 1);
} else {
reqPerm();
}
}).catch(function(err) {
//error
});
} else if (curStatus == 'denied') {
//denied
} else {
reqPerm();
}
function reqPerm() {
messaging.requestPermission().then(function() {
messaging.getToken().then(processToken);
}).catch(function(err) {
//error
});
}
function processToken(token, hasAlready) {
alert(token);
}
</script>
Found it - the phone memory was absolutely full, so Firebase script couldn't add token data to the local indexeddb of the browser. Deleted some files on device and now it works.
I'm using firestore with react native like below, but while running my app data is not added to the cloud. am not sure why, please help me to understand the actual problem here.
componentWillMount() {
console.log('Test1');
firebase.initializeApp({
apiKey: 'xxxxxxx',
authDomain: 'testing-8ex763xxxxxxxxxxxxxx',
databaseURL: 'https://testing-8e76xxxo.com',
projectId: 'testing-xxxxx',
storageBucket: 'testing-8xxxxx.com',
messagingSenderId: '73664xxx042'
});
firebase.firestore().enablePersistence()
.then(function() {
// Initialize Cloud Firestore through firebase
var db = firebase.firestore();
console.log('Test3', db);
db.collection('us').add({
first: 'hai',
last: '111',
born: 1815
})
.then(function(docRef) {
console.log("Document written with ID: ", docRef.id);
})
.catch(function(error) {
console.error("Error adding document: ", error);
});
})
.catch(function(err) {
if (err.code == 'failed-precondition') {
// Multiple tabs open, persistence can only be enabled
// in one tab at a a time.
// ...
} else if (err.code == 'unimplemented') {
// The current browser does not support all of the
// features required to enable persistence
// ...
}
});
}
You have not given the reference of doc.
And also use 'set' instead of add method.
db.collection('us').doc('some_name').set({
first: 'hai',
last: '111',
born: 1815
})