i have getting "do_not_collapse" as payload in FCM WEB notification - angularjs

i am doing fcm web notification for the first time andgeting an message as
{ from: "205864560478", collapse_key: "do_not_collapse" }
my code is
messaging.onMessage(function(payload) {
console.log("Message received. ", payload);
// ...
});
and my firebase-messaging-sw.js
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);
});
please help . i dont know why i get this error
i have perfectly working for ios and Android.
my web project is in localhost and do not have https

{ from: "205864560478", collapse_key: "do_not_collapse" } is the expected payload and it is not an error.
Also, for development, localhost is exempted from the https condition.
In FCM, if the user is currently viewing your web page and receives a push notification then it will not be shown as push notification (default behavior).
The behavior of messages differs depending on whether the page is in
the foreground (has focus), or in the background, hidden behind other
tabs, or completely closed.
When your app is in the foreground (the user is currently viewing your
web page), you can receive data and notification payloads directly in
the page.
https://firebase.google.com/docs/cloud-messaging/js/receive
If you still want to show a notification when user is currently viewing your web page then you can add push code logic at messaging.onMessage
Example
messaging.onMessage(function (payload) {
console.log('Message received. ', payload);
var options = {
body: 'Background Message body.', // payload.body
icon: '/firebase-logo.png' . // payload.icon
};
var n = new Notification('Notification says',options);
setTimeout(n.close.bind(n), 5000);
});

Related

PWA Push Notification not showing when app is not running

I'm developing a Progressive Web App with React that gets notifications when a new offer has been added to the DB. Everything works fine, I open the web, asks the user to grant permissions to enable notifications, we allow them, install the PWA, run it, add a new offer in the DB, and the a notification with the new offer gets displayed (Chrome + Windows 10).
But the issue is I don't get any notifications if the PWA is not running.. I would have thought the service worker is running in the background even if the PWA is closed. What am I missing?
here is my notifyNewOffer function in my notifications.ts file
function notifyNewOffer(newOffer: Offer) {
if ('serviceWorker' in navigator) {
const options = {
body: newOffer.subheading,
icon: './logo192.png',
image: './static/media/placeholder-offer.1bcbf040.png',
vibrate: [100, 50, 200],
badge: './favicon.ico',
tag: 'new-offers',
renotify: true,
actions: [
{ action: 'confirm', title: 'Check offer', icon: '' },
],
};
navigator.serviceWorker.ready.then(swreg => {
swreg.showNotification(newOffer.heading, options);
});
} else {
console.log('no serviceWorker');
}
}
And this is how I call it:
function addedOfferSubs<T>(setOffers: (offers:any) => void) {
// #ts-ignore
const subscription = API.graphql(graphqlOperation(addedOffer)).subscribe({
next: async (eventData: SubscriptionValue<T>) => {
const newOffer = (eventData.value.data as any).addedOffer;
await indexedDb.createObjectStore('offers', 'id'); // Opens db. Will create the table offers only if it doesnt already exist
await indexedDb.putValue('offers', newOffer); // Adds new offer
// Push notification
notifyNewOffer(newOffer);
// Set offers
const offersData = await getOffersFromIdb();
setOffers(offersData);
},
});
return () => subscription.unsubscribe()
}
Any ideas ?
Thanks very much
In order for notifications to appear when the app isn't open, you'll need to use Web Push as well. Web push allows you to send a notification from your server to device. When the push arrives on the device, it wakes up the service worker, and the notification is shown there.
Instructions for setting up Web Push & Notifications are available at https://developers.google.com/web/fundamentals/push-notifications

Can't get notification payload from firebase-sw on Ionic PWA

I've searched a lot for this problem that I'm stuck on for a week.
I have an Ionic PWA project that receive some notifications from firebase, I can receive the notifications with no problem and can get the payload on foreground (app is open), but I cant get the payload when the app is closed and I don't figure out what is goning on, so I came here to ask the masters to help me.
messaging.setBackgroundMessageHandler(function(payload) {
var notificationTitle = 'Teste';
var notificationOptions = {
body: 'Background Message body.',
tag: 'campanhas',
data: payload.data,
icon: 'https://firebasestorage.googleapis.com/v0/b/hemotomobile-edeb9.appspot.com/o/logo.png?alt=media&token=4a9fc487-b8cf-4d3c-875c-774454ff6f50'
};
return self.registration.showNotification(notificationTitle,
notificationOptions);
});
self.addEventListener('notificationclick', function(event) {
event.notification.close();
event.waitUntil(clients.matchAll({
type: "window"
}).then(function(clientList) {
for (var i = 0; i < clientList.length; i++) {
var client = clientList[i];
if (client.url == '/' && 'focus' in client)
return client.focus();
}
if (clients.openWindow)
return clients.openWindow('/');
}));
});
and on my provider for the notifications, I use this code:
public receiveMessage() {
console.log('notification')
this.messaging.onMessage((payload) => {
console.log('payload',payload)
});
}
I call this provider on my tabs-page:
ionViewDidLoad(){
this.notification.receiveMessage()
}
So, can anyone help me to get the payload when the PWA is closed?
have you tried by initializing firebase in the service worker and using it ,
self.addEventListener("notificationclick", (event) => {
//your code
});
importScripts("https://www.gstatic.com/firebasejs/4.7.0/firebase.js")
importScripts("https://www.gstatic.com/firebasejs/4.7.0/firebase-messaging.js")
// Initialize Firebase
firebase.initializeApp({
'messagingSenderId': 'your sender id'
});
const messaging = firebase.messaging();
messaging.setBackgroundMessageHandler(function(payload) {
//your code
});
this.messaging.onMessage((payload) => {
//your code
});
self.addEventListener('notificationclose', function (event) {
self.registration.getNotifications().then(function (notifications) {
notifications.forEach(function (notification) {
notification.close()
})
});
})
I have tried by using above code in the service worker and it is showing notification when the application is closed , if you want to show the notification when the browser is closed make sure you have enabled the Continue running background apps when Google Chrome is closed option in chrome settings.

Incorporating Socket.IO in React Application

I am trying to incorporate socket.io in a React application. When the user clicks a button, I want the program to display a modal notifying all other users that the button has been clicked. In my current implementation, I set up the socket.io connection in my server.js file and use socket.io-client in one of the component files to send / listen for information from the server.
Server.js file:
io.on("connection", function(socket) {
console.log("Socket.io connection established");
socket.emit("saved article", function(article){
console.log("article saved");
io.emit("saved article", article);
});
});
Component file:
const socket = io();
class Search extends Component {
state = {
topic: "",
start: "",
end: "",
results: [],
savedModalTriggered: false,
articlesSaved: []
};
componentDidMount(){
socket.on("saved article", article => {
let articlesSavedCopy = this.state.articlesSaved;
articlesSavedCopy.push(article.title);
this.setState({savedModalTriggered: true, articlesSaved: articlesSavedCopy});
});
};
saveOrUnsave = (index) => {
API.saveArticle(this.state.results[index]).then(response => {
const article = {
title: response.data.title
};
socket.emit("saved article", article);
this.reverseSaved(index, response.data);
});
};
};
The following problems arise when I run my code:
1) When the Search component mounts, the program triggers socket.on("saved article"), causing the notification modal to pop up even though the saveOrUnsave function was not called.
2) After some period of time, I get the following error in my console: "WebSocket connection to localhost:3000... failed: Connection closed before receiving a handshake response"
3) I also get the following error in my console: "WebSocket connection to localhost:3000... failed: WebSocket opening handshake timed out"
The problem is that you are emitting a saved article event upon connection. When the client opens a new connection in the componentDidMount callback the server emits an event, thus triggering the callback you have registered.
If that is not what you want you should remove the emit logic from your connection callback in the server code.

Twilio & NodeJS: can't find and delete Media instances/resources

I'm using Twilio's NodeJS module & API to send out MMS messages with images attached (from a remote URL), and I want to delete the Media instances that get created on Twilio servers as soon as I send out the messages.
My messages send out correctly, and in the callback, I'm trying to 1) list media instances for the current message, then 2) loop through those instances and delete. The problem is that the mediaList array that comes back from the API for a current message is always empty.
Here's my code:
twilio_client.messages.create({
body: "Thanks for taking a photo. Here it is!",
to: req.query.From,
from: TWILIO_SHORTCODE,
mediaUrl: photo_URL,
statusCallback: STATUS_CALLBACK_URL
}, function(error, message) {
if (!error) {
twilio_client.messages(message.sid).media.list(function(err, data) {
console.log(data);
// The correct object comes back as 'data' here per the API
// but the mediaList array is empty
}
console.log('Message sent via Twilio.');
res.status(200).send('');
} else {
console.log('Could not send message via Twilio: ');
console.log(error);
res.status(500).send('');
}
});
So, it turns out that trying to get the media list at the point I was trying to doesn't work because the media instances didn't exist yet.
I have a separate little app running at the statusCallback (I supply a URL via a constant in the code above, STATUS_CALLBACK_URL), that until now, just checked to see if a message I tried to MMS to a user wasn't handled properly by Twilio, and alerted the user to a problem via SMS. So, I added a check in that same app to see if the message was actually 'sent' to the user, and then checked for and deleted the media instance(s) associated with the message at that point, and it works fine. Here's my code:
// issue message to user if there's a problem with Twilio getting the photo
if (req.body.SmsStatus === 'undelivered' || req.body.SmsStatus === 'failed') {
twilio_client.messages.create({
body: "We're sorry, but we couldn't process your photo. Please try again.",
to: req.body.To,
from: TWILIO_SHORTCODE
}, function(error, message) {
if (!error) {
console.log('Processing error message sent via Twilio.');
res.send(200,'');
} else {
console.log('Could not send processing error message via Twilio: ' + error);
res.send(500);
}
});
}
// delete media instance from Twilio servers
if (req.body.SmsStatus === 'sent') {
twilio_client.messages(req.body.MessageSid).media.list(function(err, data) {
if (data.media_list.length > 0) {
data.media_list.forEach(function(mediaElement) {
twilio_client.media(mediaElement.sid).delete;
console.log("Twilio media instance deleted");
});
}
});
}

In GAE Channel API the onmessage is not called

I am building an app for GAE using python API. It is running here. It is a multi-player game. I use the Channel API to communicate game state between players.
But in the app engine the onmessage handler of the channel is not called. The onopen handler is called. onerror or onclose are not called as well. Weird thing is this works perfectly in the local development server.
Is it possible that something like this can work on the development server but not in the app engine itself?
I'll be really really glad if someone can look into following description of my app and help me to figure out what has happened. Thank you.
I looked into this and this questions, but I haven't done those mistakes.
<script>
sendMessage = function(path, opt_param, opt_param2) {
path += '?g=' + state.game_key;
if (opt_param) {
path += '&' + opt_param;
}
if (opt_param2) {
path += '&' + opt_param2;
}
var xhr = new XMLHttpRequest();
xhr.open('POST', path, true);
xhr.send();
};
Above function is used to make a post request to the server.
onOpened = function() {
sendMessage('/resp');
console.log('channel opened');
};
Above is the function I want to be called when the channel is open for the first time. I send a post to the '/resp' address.
onMessage = function(m) {
console.log('message received');
message = JSON.parse(m.data);
//do stuff with message here
};
I want to process the response I get from that request in the above function.
following are onerror and onclose handlers.
onError = function() {
console.log('error occured');
channel = new goog.appengine.Channel('{{ token }}');
socket = channel.open();
};
onClose = function() {
console.log('channel closed');
};
channel = new goog.appengine.Channel('{{ token }}');
socket = channel.open();
socket.onopen = onOpened;
socket.onmessage = onMessage;
socket.onclose = onClose;
socket.onerror = onError;
</script>
This script is at the top of body tag. This works fine in my local development server. But on the app engine,
onOpen function is called.
I can see the request to /resp in the sever logs.
but onMessage is never called. The log 'message received' is not present in the console.
this is the server side.
token = channel.create_channel(user.user_id() + game.user1.user_id() )
url = users.create_logout_url(self.request.uri)
template_values = {
'token' : token,
'id' : pid,
'game_key' : str(game.user1.user_id()),
'url': url
}
path = os.path.join(os.path.dirname(__file__), 'game.html')
self.response.out.write(template.render(path, template_values))
and this is in the request handler for '/resp' request. My application is a multi-player card game. And I want to inform other players that a new player is connected. Even the newly connected player will also get this message.
class Responder(webapp2.RequestHandler):
def post(self):
user = users.get_current_user()
game = OmiGame.get_by_key_name(self.request.get('g'))
if game.user1:
channel.send_message(game.user1.user_id() + game.user1.user_id() , create_message('%s joined.' % user.nickname()))
if game.user2:
channel.send_message(game.user2.user_id() + game.user1.user_id() , create_message('%s joined.' % user.nickname()))
EDIT : user1 is the user who created the game. I want tokens of other players' to be created by adding the user1's user_id and the relevant users user_id. Could something go wrong here?
So when I try this on the local dev server I get these messages perfectly fine. But on the GAE onMessage is not called. This is my app. When the create button is clicked page with above script is loaded and "playernickname connected" should be displayed.
The channel behavior on the dev server and production are somewhat different. On the dev server, the channel client just polls http requests frequently. On production, comet style long polling is used.
I suspect there may be a problem with making the XHR call inside the onOpened handler. In Chrome at least, I see that the next talkgadget GET request used by the channel API is cancelled.
Try calling sendMessage('/resp') outside of the onMessage function. Perhaps enqueue it to get run by using setTimeout so it's called later after you return.

Resources