Firebase Cloud Messaging push notification not being sent to device - ios

This is what my log looks like when my push notification gets called on
I am currently working on creating push notification set up for a user to user setting for the iPhone. I am currently using Firebase, so naturally I turned to Firebase Cloud Messaging to get this done. This is my setup in the functions that I am deploying to my Firebase. Is there something that I am doing wrong in here that would result in the notification not being sent to the device? I appreciate any help, and if there is any more needed information I would be happy to supply it.
const functions = require('firebase-functions');
const admin = require('firebase-admin');
admin.initializeApp(functions.config().firebase);
// Listens for new messages added to messages/:pushId
exports.pushNotification = functions.database.ref('/messages/{pushId}').onWrite( event => {
console.log('Push notification event triggered');
// Grab the current value of what was written to the Realtime Database.
var valueObject = event.data.val();
console.log(valueObject)
if(valueObject.photoUrl != null) {
valueObject.photoUrl= "Sent you a photo!";
}
// Create a notification
const payload = {
notification: {
title:valueObject.toId,
body: valueObject.text || valueObject.photoUrl,
sound: "default"
},
};
//Create an options object that contains the time to live for the notification and the priority
const options = {
priority: "high",
timeToLive: 60 * 60 * 24
};
return admin.messaging().sendToTopic("pushNotifications", payload, options);
if(!data.changed()){
});
exports.pushNotification = functions.database.ref('/messages/{pushId}').onWrite( event => {
const data = event.data;
console.log('Push notification event triggered');
return;
}
});

I noticed that you are exposing the same function twice. That is also an issue. Also I suggest you to promisify the admin.messaging, so that you can handle and check for errors.
let topic = "pushNotifications";
admin.messaging().sendToTopic(topic, payload, options)
.then(function(response) {
console.log("Successfully sent message:", response);
console.log("Topic: " + topic);
res.status(200).send("success");
})
.catch(function(error) {
console.log("Error sending message:", error);
res.status(500).send("failure");
});

Send this jsone on your post parameter in registration_ids field you have to post array of your All device token that you want to send push notification
This is post request method body
{ "registration_ids" : [Send Array of Device Token],
"data" :
{
"image_url" : "send your image here"
"message" : "Send your message here" },
"notification" :
{
"title" : "APP Name",
"sound" : "default",
"priority" : "high"
}
}
Here is post URL
https://fcm.googleapis.com/fcm/send
and send key="Your Authorization key" in request HttpHeader field
Take reference for basic setup form here for cloud messaging
https://firebase.google.com/docs/cloud-messaging/ios/client

Related

how to send silent notification / background notification using Firebase Cloud Messaging?

I need to make silent notification/background notification in my iOS app using Firebase Cloud Messaging, so I can make an update in the app even though the user doesn't tap the push notification.
the documentation from Apple about background notification is in here , it is said that
To send a background notification, create a remote notification with
an aps dictionary that includes only the content-available key in the payload
Sample payload for a background notification from that documentation is like this:
{
"aps" : {
"content-available" : 1
},
"acme1" : "bar",
"acme2" : 42
}
so I create my own payload when sending FCM using cloud function node JS. my code is like this
const userToken = device.token
const payload = {
data: {
notificationID : notificationID,
creatorID : moderatorID,
creatorName: creatorName,
title : title,
body : body,
createdAt : now,
imagePath : imagePath,
type: type
},
apps : {
"content-available" : 1 // to force background data update in iOS
}
}
await admin.messaging().sendToDevice(userToken,payload)
I try to send and I have error:
'Messaging payload contains an invalid "apps" property. Valid
properties are "data" and "notification".
so adding "apps" property is not allowed, but iOS documentation said that I need to add "content-available" in the payload.
I read other answer in here, it is said that the payload should be written like this
{
"to" : "[token]",
"content_available": true,
"priority": "high",
"data" : {
"key1" : "abc",
"key2" : abc
}
but I am confused how to write the payload FCM that can trigger background notification in iOS
Based on the error message that you are receiving, you should remove the apps property since data and notification properties are considered to be valid, as per the documentation.
Now, in regards to the the payload that you found elsewhere, this refers to the HTTP syntax used to pass messages from your app server to client apps via Firebase Cloud Messaging using the FCM legacy HTTP API. You can refer to the the documentation to learn more about the new HTTP v1 API.
To answer your question, when you are using a Cloud Function with Node.js runtime to send notifications using the sendToDevice(token, payload, options) method, you will need to pass the contentAvailable in the function's options parameter.
The contentAvailable option does the following: When a notification or message is sent and this is set to true, an inactive client app is awoken, and the message is sent through APNs as a silent notification and not through the FCM connection server.
Therefore, your Cloud Function might look something like this:
const userToken = [YOUR_TOKEN];
const payload = {
"data": {
"story_id": "story_12345"
},
"notification": {
"title": "Breaking News"
}
};
const options = {
"contentAvailable": true
};
admin.messaging().sendToDevice(userToken, payload, options).then(function(response) {
console.log('Successfully sent message:', response);
}).catch(function(error) {
console.log('Error sending message:', error);
});

how to trigger push notifications of firebase from an ios device using swift3

I am new iOS developer.
I am using firebase and I am trying to make a chat application in which I need to notify user when he/she receives any message.
For this purpose I tried firebase push notifications, but couldn't be able to trigger them when other user send the message.
The only way I found is using firebase console to send push notification, but it doesn't fulfill my requirements.
I've just configured local notifications.
Please guide me how can we trigger push notifications without using the firebase console.
Finally found the solution after struggling for almost 1 month.
These are the basic steps
Firs off all you need to make sure that you have an active apple developers account
just enable firebase push notifications
here ie the link of youtube video for this step
Now your app is set up for firebase remote notifications but we can only trigger them from the firebase console so here is the tricky part. here is the link of video to enable firebase console on your mac
for the first time it will be good to see this video too because in this video they'll learn to write code in node.js and deploy it to the firebase.
Now if anyone wants to make an API instead of making a trigger then here is a code of API which sends the notification to other user by getting his FCM token from the firebase...
You can modify it according to your need
i am finding it difficult to post code in its exact form but the code starts from here
const functions = require('firebase-functions');
const admin =require('firebase-admin');
admin.initializeApp(functions.config().firebase);
const ref=admin.database().ref();
exports.sendNotification=functions.https.onRequest((req,res) =>{
const id = req.query.id
const title = req.query.title
const message = req.query.message
const key = req.query.key
// admin.database.ref()
const payload ={
notification: {
title: title,
body: message,
//badge: '1',
sound: 'default',
}
};
console.log('Param [key] is '+key);
const keys = [] ;
ref.child('keys').once('value')
.then(snap => {
snap.forEach(childSnap => {
const loopKey=childSnap.val().key;
keys.push(loopKey);
})
return keys;
})
.then(keys=>{
//console.log('Keys in database : '+keys.join());
if(keys.indexOf(key)>-1)
{
if(!key || !id || !message)
{
res.status(400).send('Bad request');
}
else{
ref.child('users').child(id).child('fcmToken').once('value')
.then(snapshot => {
if (snapshot.val()){
const token = snapshot.val()
console.log(token);
return admin.messaging().sendToDevice(token,payload).then(response =>{
res.status(200).send('Notification sent')
});
}
});
}
}
else
{
console.log("In-valid key : "+key);
res.status(400).send('Bad request');
}
})
.catch(error => {
res.send(error)
});
});
ends at this point
this is the function to store your fcm to database
func postToken(token: String, id: String){
print("FCM Token \(token)")
let ref = Database.database().reference().child("users").child(id)
ref.child("fcmToken").setValue(token)
}
here is the function which i used to trigger this API
func sendNotification(id: String, title: String, message: String){
var url = "your URL"
var urlComponents = NSURLComponents(string: url)
urlComponents?.queryItems = [
URLQueryItem(name: "key", value: self.apiKey),
URLQueryItem(name: "id", value: id),
URLQueryItem(name: "title", value: title),
URLQueryItem(name: "message", value: message)
]
Alamofire.request((urlComponents?.url)!).responseJSON { (response) in
print(response.response)
print(response.response)
print(response.result)
}
}
the above API was written according to my database structure. you can change it easily for your own structure.
after doing this all you'll be able to send your notifications after hitting the URL
Hope it will give a nice idea to you people to work with your own notifications according to your need.
I was able to send Push Notifications from my code using PushNotificationSender class from this article -
https://www.iosapptemplates.com/blog/ios-development/push-notifications-firebase-swift-5

Can I send a silent push notification from a Firebase cloud function?

Is it possible to send a silent APNs (iOS) remote notification from a Firebase Cloud Function? If so, how can this be done? I want to send data to iOS app instances when the app is not in the foreground, without the user seeing a notification.
I currently send a notification that can be seen by users:
const functions = require('firebase-functions');
const admin = require('firebase-admin');
admin.initializeApp(functions.config().firebase);
exports.sendNotifications = functions.database.ref('/events/{pushId}').onWrite(event => {
const id = event.params.pushId
const payload = {
notification: {
title: 'An event has occurred!',
body: 'Please respond to this event.',
event_id: id
}
};
return admin.messaging().sendToTopic("events", payload);
});
I would like to be able to send that id to the app without a visual notification.
I figured out how to modify my code to successfully send a silent notification. My problem was that I kept trying to put content_available in the payload, when it really should be in options. This is my new code:
const functions = require('firebase-functions');
const admin = require('firebase-admin');
admin.initializeApp(functions.config().firebase);
exports.sendNotifications = functions.database.ref('/events/{pushId}').onWrite(event => {
const id = event.params.pushId
const payload = {
data: {
title: 'An event has occurred!',
body: 'Please respond to this event.',
event_id: id
}
};
const options = {
content_available: true
}
return admin.messaging().sendToTopic("events", payload, options);
});
I successfully received the silent notification on my iOS device after implementing application:didReceiveRemoteNotification:fetchCompletionHandler and userNotificationCenter:willPresent:withCompletionHandler.
If you're talking about APNs notifications, the answer is: No, you can't send a notification without visualisation. You can only disable a sound. But, you can passed an FCM Data message without visualisation. You can read about it here: https://firebase.google.com/docs/cloud-messaging/concept-options
{
"to" : "bk3RNwTe3H0:CI2k_HHwgIpoDKCIZvvDMExUdFQ3P1...",
"data" : {
"Nick" : "Mario",
"body" : "great match!",
"Room" : "PortugalVSDenmark"
}
}

is there any way to send different badge count to different users in a same topic?

I have FCM integration in my Node.js project where I am sending number of notifications to the IOS users and I need to manage notification count i.e. Badge count which will be different across the devices but I am sending notification to a particular topic to which these devices are subscribed.
my Payload is :
var payload = {
notification: {
title: "Title...",
body: "Notification Body...",
sound: "customeSound.caf",
badge : "?"
},
data: {
testData: "custom data"
}
},
topic = "topicName";
admin.messaging().sendToTopic(topic, payload)
.then(function (response) {
// See the MessagingTopicResponse reference documentation for the
// contents of response.
console.log("Successfully sent message:", response);
})
.catch(function (error) {
console.log("Error sending message:", error);
});
});
All devices that are subscribed to the corresponding topic will receive the same payload you set.
You'll have to send a separate payload for each device. Or if applicable, maybe just group the ones with the similar badge value -- but that would require you to send to a group of tokens (using registration_ids) instead of sending to a topic.
If you have the devices tokens and you want to send the badge counts to respective device token,
Instead of sending them one by one ( Which I personally think is not a good idea) the best alternative you can do is:-
You can achieve this by doing something like.....
First of all you need to query your DB to get the device token and badge count respectively
So say like you have and array
const badgeCounts = [{
device_token:'aaaaaaaaaaaaaaaaaaaaaa',
badge_count: 1
},{
device_token:'bbbbbbbbbbbbbbbbbbbbbb',
badge_count: 2
},{
device_token:'cccccccccccccccccccccc',
badge_count: 3
},{
device_token:'dddddddddddddddddddddd',
badge_count: 4
}]
Now you can map over this array and compose array of fcm messages, something like below :-
const fcmMessages = [];
badgeCounts.forEach((data) => {
fcmMessages.push({
token: data.device_token, //device token
apns: {
payload: {
aps: {
alert: {
title: "your title",
body: "your body",
},
badge: data.badge_count, // badge
contentAvailable: true,
},
},
},
data: {
// any payload goes here...
},
notification: {
title: "your title",
body: "your body",
},
});
});
/// in firebase messiging you can do like
messaging.sendAll(fcmMessages);
refer doc https://firebase.google.com/docs/reference/admin/node/admin.messaging.Messaging-1#sendall

Firebase Cloud Messaging not sending aps payload in correct format for iOS Notification Content & Service Extensions

I'm trying to implement notifications using Firebase. The notification is received correctly when the app is in the background or foreground. So, the basic mechanics are working.
Now I've added Content Extensions and Service Extensions to the app. The Content Extension works when I use a local notification, but the Firebase message payload seems incorrect as far as the optional fields are considered. Here is a link to an image of my console:
And here is the Firebase remote notification payload that comes across (with some of the long Google numbers edited for anonymity:
{
aps =
{
alert =
{
body = "Eureka! 11";
title = "Patient is not doing well";
};
};
category = provider-body-panel;
gcm.message_id = 0:149073;
gcm.n.e = 1;
google.c.a.c_id = 2825604;
google.c.a.e = 1;
google.c.a.ts = 149073;
google.c.a.udt = 0;
mutable-content = 1;
}
It appears that the "category" and "mutable-content" are not in the correct place. They should be in the aps payload.
How can I get those options to be in the payload so that my app can correctly parse it and connect it with the Content and Service Extensions?
To start off, I'm going to mention that there are two types of message payloads for FCM. notification and data. See the documentation here
When sending notifications through the Firebase Notifications Console, it will be treated as a notification payload. However, if you add in Custom Data, it will add it in the payload as a custom key-value pair.
For example, in your post, the FCM payload should look something like this:
{
"notification": {
"body" : "Eureka!",
"title": "Patient is not doing well"
},
"data": {
"category": "provider-body-panel",
"mutable-content" : true,
"click_action" : "provider-body-panel"
}
}
What's wrong?
click_action should be inside notification.
mutable-content should be mutable_content (notice the underscore) and should be on the same level as notification.
(this one I might've misunderstood, but) There is no category parameter for FCM, click_action already corresponds to it.
See the docs for the parameters here.
It it is currently not possible to set the value for click_action and mutable_content when using the Firebase Notifications Console. You'll have to build the payload yourself, something like this:
{
"to": "<REGISTRATION_TOKEN_HERE>",
"mutable_content" : true,
"notification": {
"body" : "Eureka!",
"title": "Patient is not doing well",
"click_action" : "provider-body-panel"
}
}
Then send it from your own App Server. You could also do this by using Postman or cURL
"mutable-content should be "mutable_content" (keyword for firebase server to send as mutable-content for IOS) as you mentioned in your post, I think you left out in edit.
Below is an example with also the corrected format for the data section in the json sent to the FCM server.
So update would be:
{
"to" : "YOUR firebase messaging registration id here",
"mutable_content":true,
"notification": {
"title": "Its about time",
"body": "To go online Amigo",
"click_action": "NotificationCategoryIdentifier ForYourNotificationActions"
},
"data":{
"customKey":"custom data you want to appear in the message payload"
"media-attachment":"mycustom image url",
"catalogID":"mycustom catalog for my custom app"
}
}
Update Firebase Admin SDK and use sendMulticast(payload) method
var admin = require("firebase-admin")
admin.initializeApp({
credential: admin.credential.applicationDefault(),
});
// Create a list containing up to 500 registration tokens.
// These registration tokens come from the client FCM SDKs.
const registrationTokens = [
'YOUR_REGISTRATION_TOKEN_1',
// …
'YOUR_REGISTRATION_TOKEN_N',
];
// See documentation on defining a message payload.
var message = {
notification: {
title: '$FooCorp up 1.43% on the day',
body: '$FooCorp gained 11.80 points to close at 835.67, up 1.43% on the day.'
},
tokens: registrationTokens,
apns: {
payload: {
aps: {
'mutable-content': true, // use single quote
'category': 'INVITE_CATEGORY' // use single quote
}
},
},
};
// Send a message to the device corresponding to the provided
// registration tokens.
admin.messaging().sendMulticast(message)
.then((response) => {
if (response.failureCount > 0) {
const failedTokens = [];
response.responses.forEach((resp, idx) => {
if (!resp.success) {
failedTokens.push(registrationTokens[idx]);
}
});
console.log('List of tokens that caused failures: ' + failedTokens);
}
});
Ref: https://firebase.google.com/docs/cloud-messaging/send-message#send_messages_to_specific_devices
This worked for me with Cloud functions with Node.js
const payload = {
notification: {
title: name,
body: messageText,
badge: "1",
mutable_content: "true"
},
data: {
type: "MESSAGE",
fromUserId: name,
attachmentUrl: imageUrl
}};

Resources