How to collapse a Web Push notification sent by FCM - firebase

I'm using FCM with firebase-admin to send a Web Push notification for multiple clients. I want to replace an older message by a new one.
This is how I'm calling it:
return await admin.messaging().sendMulticast({
tokens,
notification: {
title: "Message Title",
body: "Message body.",
},
data: {
type: "ring",
callId,
},
webpush: {
fcmOptions: {
link: process.env.PWA_APP_URL,
},
headers: {
Urgency: "high",
},
},
android: {
collapseKey: "ring",
priority: "high",
ttl: 10,
notification: {
color: "#ff0000",
defaultSound: true,
sound: "default",
lightSettings: {
color: "#ffcc00",
lightOffDurationMillis: 1000,
lightOnDurationMillis: 1000,
},
tag: "ring",
vibrateTimingsMillis: [1000, 1000],
visibility: "public",
priority: "max",
},
},
});
When the message arrives to an Android app client it's collapsed because of android.collapseKey property. But I can't get the same behavior in my web application.
According to the docs, there's a Topic option for Web notifications, but I'm not sure where to put it. I tried to use it as webpush.headers.Topic property but with no success. Messages are not collapsed in Android/Chrome.
What am I doing wrong?

I've followed collimarco's tip and could use showNotification method to collapse a notification.
In firebase-admin/server code I had to remove the notification fields in the message's payload. Now it's just a data message:
return await admin.messaging().sendMulticast({
tokens,
data: {
type: "ring",
callId,
},
});
In the web application I created a background message handler. Now I can call showNotification method when I new message arrives using tag property with renotify=true.
messaging.setBackgroundMessageHandler(function (payload) {
// ...
return self.registration.showNotification("Message Title", {
body: "Message body.",
tag: "ring",
renotify: true,
vibrate: [1000, 1000],
});
});
It would be great to have these properties set on the message payload only.

Related

How to achieve time-sensitive flag in APNS JSON output via FCM?

iOS distinguishes between messages by UNNotificationInterruptionLevel. I would like to achieve that messages sent via FCM have the time-sensitive interruption-level.
Is this equivalent to just sending messages in FCM with high priority? Unfortunately it's not super clear to me from looking at the docs.
The interruption level is automatically handled by system, not by FCM. That's different than the high priority.
You should be able to use it as it is by following Apple's documentation. FCM supports passing down the interruption-level in the payload.
I achieved this by having this payload in my firebase console file:
var message = {
notification: {
title: "Notification Title",
body: `${initiatedUsername} sent you message`,
},
"data": {
"target_exec":"messaging"
},
"apns": {
"payload": {
"aps": {
"alert": {
"title": "Notification Title",
"body": `${initiatedUsername} sent you a message`
},
"badge": 1,
"sound": "default",
"interruption-level": "time-sensitive"
}
}
},
token: fcmToken,
};
You can change the token attribute to topic aswell, if you'd rather like to send a message to a topic.
Hope this might help somebody out here!

Flutter - Background notifications not working in iOS

I'm creating a public chat app in Flutter, and I can't receive background notifications on iOS, when I trigger the method admin.messaging().send(payload) from my Cloud Function.
Here's my payload in the Cloud Function :
var payload = {
notification: {
title: `My Title`,
body: `My message`,
},
android: { priority: "high" },
apns: {
payload: {
aps: {
contentAvailable: true,
},
},
headers: {
"apns-push-type": "background",
"apns-priority": "10",
"apns-topic": "io.flutter.plugins.firebase.messaging", // bundle identifier
},
},
topic: `mytopic`,
};
I tried a bunch of different payloads :
I tried notification + data
I tried only data (no notification) (in that case, I have to locally display the notification, but it is not working because the function FirebaseMessaging.onBackgroundMessage is never called)
I tried to change "apns-priority" to 5
I tried using a token instead of a topic
I set up carefully all I need to configure, thanks to the official documentation :
https://firebase.flutter.dev/docs/messaging/usage/
I also checked Github issues, like these ones :
1041, 6112, 5988, 1644, 4300, 4097
What is working :
Background and foreground notifications on Android and iOS, when sent from Firebase Console (in 'Cloud Messaging' section)
Background and foreground notifications on Android only, when sent from Cloud Function
Foreground notifications on iOS, when sent from Cloud Function
What is NOT working :
Background notifications on iOS when sent from Cloud Function
When app is terminated, it does not work as well.
I finally resolved this issue ! 🎉
I simply removed the line "apns-push-type": "background" in my payload.
Now it is working.
It appears that the line "apns-topic" was useless as well.
Here is my final payload :
var payload = {
notification: {
title: `# ${context.params.passion}`,
body: `${newMsg["senderPseudo"]} ${
type == "image" ? "a envoyé une image." : `: ${newMsg["message"]}`
}`,
},
// Set Android priority to "high"
android: {
priority: "high",
},
// Add APNS (Apple) config
apns: {
payload: {
aps: {
contentAvailable: true,
},
},
headers: {
//"apns-push-type": "background", // This line prevents background notifications to be displayed
"apns-priority": "10",
},
},
token: "dnqTQVso60GfnnuOjHv8_e:APA91bElr-K3xkQMdYHX8VMrMZNCYCjO4zJlGseRh25AS_GT7cg9zlOGdQl4KXvr88ypeWjZjrPzrLRHitsQ-JKQK057ZQb_36c_lfsNjHXbYMYI2iS3jV_HGWf7Ene-ZlPvOb0aRr8u"
};

Redirect URL in push notification on PWA

Currently, I'm starting a PWA in Angular. I need to intercep some push notifications and redirect to this application when I click on the notification. I'm using Firebase for the push server.
Today, I can receive push notifications but when i click on one of them, I'm not redirected.
I send my request with Postman, my HTTP request is like :
POST /fcm/send HTTP/1.1
Host: fcm.googleapis.com
Authorization: key=XXXX
Content-Type: application/json
{
"to":"XXXX",
"content_available": true,
"notification": {
"title": "hello",
"body": "test message",
"data": {
"url": "http://myurl.com"
}
}
}
In my web application, I receive the following datas :
data:
gcm.notification.content_available: "true"
gcm.notification.data: "{"url":"http:\/\/myurl.com"}"
extra: "juice"
from: "300398521917"
notification:
title: "hello"
body: "test message"
collapse_key: "do_not_collapse"
And, when I click on the receive notification, my application intercept the event and log :
action: ""
notification:
actions: []
badge: ""
body: "test message"
data: null
dir: "auto"
icon: ""
image: ""
lang: ""
renotify: false
requireInteraction: false
silent: false
tag: ""
timestamp: 1582539931548
title: "hello"
vibrate: []
I would like to refind my url in the data part. Anybody have an idea about this ?
I have tried like below its worked for me
{
"to":"XXXX",
"content_available": true,
"notification": {
"title": "hello",
"body": "test message",
"click_action": "https://example.com"
}
}
self.registration.showNotification method takes notificationOptions as parameter. So you can pass data object (that will have url and other custom properties that you want to pass) to inside notificationOption object then in notificationclick listener, get that object event.notification.data and access all custom properties there.This way you can url to listener.
messaging.onMessage(function(payload){
var dataObj = payload.data;
dataObj.someCustomProperty = "xyz";
const notificationOptions = {
data: dataObj
};
self.registration.showNotification(payload.title,
notificationOptions);
)
self.addEventListener('notificationclick', function(event){
const nUrl = event. notification.data.customProperty;
})

How to create APNS payload for Firebase?

I have connected my IONIC 4 app to Firebase and then to AWS SNS.
Everything works perfectly for Android, the push notifications are delivered.
But iOS devices never receives them. I have made all the necessary configs, certificates and keys. When I publish a test message via Firebase Console, the iOS devices receive the notifications.
I get a little confuse about this payload object and I guess it might be causing this issue.
The payload object (ignore the values):
var payload = {
default: "Trokaí",
GCM: {
data: { message: "A", payload: "", title: "C" },
notification: {
message: "E",
payload: "F",
title: "Trokaí",
body: msgPush
}
},
APNS: {
aps: {
alert: {
title: "Game Request",
body: "Bob wants to play poker",
"action-loc-key": "PLAY"
},
badge: 5
},
acme1: "bar",
acme2: ["bang", "whiz"]
}
};
payload.GCM = JSON.stringify(payload.GCM);
payload.APNS = JSON.stringify(payload.APNS);
payload = JSON.stringify(payload);
The publishing method:
sns.publish(
{
Message: payload,
MessageStructure: "json",
TargetArn: device.endpoint
},
function(err, data) {
if (err) {
return;
}
}

HTTP.post to FCM Server not working

I am using Ionic 2 with HTTP native module to make a post request to FCM server for push notifications. The code I am using is:
HTTP.post(
"https://fcm.googleapis.com/fcm/send",
{
"notification": {
"title": "Notification title",
"body": "Notification body",
"sound": "default",
"click_action": "FCM_PLUGIN_ACTIVITY",
"icon": "fcm_push_icon"
},
"data": {
"hello": "This is a Firebase Cloud Messagin hbhj g Device Gr new v Message!",
},
"to": "device token",
},
{
Authorization: {
key: "AUTHORIZATION KEY HERE"
}
})
Its giving me an error:
Unimplemented console API: Unhandled Promise rejection:
Unimplemented console API: Error: Uncaught (in promise): [object Object]
I tried the post request with Postman, it works perfectly fine delivering push notifications.
The code with Postman is:
POST /fcm/send HTTP/1.1
Host: fcm.googleapis.com
Content-Type: application/json
Authorization: key=Authorisation Key
Cache-Control: no-cache
Postman-Token: 446e253b-179a-d19b-21ea-82d9bb5d4e1c
{
"to": "Device Token",
"data": {
"hello": "This is a Firebase Cloud Messagin hbhj g Device Gr new v Message!",
}
"notification":{
"title":"Notification title",
"body":"Notification body",
"sound":"default",
"click_action":"FCM_PLUGIN_ACTIVITY",
"icon":"fcm_push_icon"
},
}
Questions:
I am unable to add content-type to the header in the HTTP post request, but it works with postman.
If I try to add a function(response) { to get the response from the server, it gives me an error. The documentation for the same is at https://github.com/wymsee/cordova-HTTP
why are you using HTTP native module? Angular has a built in Http.
Using this one (importing HttpModule from #angular/http in your NgModule) you can just call
import { Http, Headers } from '#angular/http';
......
constructor(public http: Http) { }
sendPushNotification(deviceId: string) {
let url = 'https://fcm.googleapis.com/fcm/send';
let body =
{
"notification": {
"title": "Notification title",
"body": "Notification body",
"sound": "default",
"click_action": "FCM_PLUGIN_ACTIVITY",
"icon": "fcm_push_icon"
},
"data": {
"hello": "This is a Firebase Cloud Messagin hbhj g Device Gr new v Message!",
},
"to": "device token"
};
let headers: Headers = new Headers({
'Content-Type': 'application/json',
'Authorization': 'key='+this.someKey
});
let options = new RequestOptions({ headers: headers });
console.log(JSON.stringify(headers));
this.http.post(url, body, headers).map(response => {
return response;
}).subscribe(data => {
//post doesn't fire if it doesn't get subscribed to
console.log(data);
});
}
push.on('notification', (data) => {
if (data.additionalData.foreground) {
// if application open, show popup
let confirmAlert = this.alertCtrl.create({
title: data.title,
message: data.message,
buttons: [{
text: 'Ignore',
role: 'cancel'
}, {
text: 'Go to',
handler: () => {
//TODO: Your logic here
this.navCtrl.setRoot(EventsPage, {message: data.message});
}
}]
});
confirmAlert.present();
} else {
//if user NOT using app and push notification comes
//TODO: Your logic on click of push notification directly
this.navCtrl.setRoot(EventsPage, {message: data.message});
}
});
push.on('error', (e) => {
alert(e);
});
});

Resources