I am new to Firebase and the main reason I adapted to it from my old MySql DB is the ability to send push notification and dynamic links. I have been trying for the past two days to send notification to a group of people who have subscribed to a topic from my node.js script. The script always returns InternalServerError. I am able to send notification from the Firebase console but that is not good enough for my app as I need to implement dynamic notification (i.e. triggered by one users action).
So far I did not understand what was in the official docs and tried following a tutorial I found and I am currently here
app.get('/push',function(req,res){
/*var title = req.params.title;
var body = req.params.body;*/
// var confName = req.params.name;
var message = { //this may vary according to the message type (single recipient, multicast, topic, et cetera)
to: '/topics/ilisten',
// collapse_key: 'your_collapse_key',
notification: {
title: 'This is Title',
body: 'This is body'
},
data: { //you can send only notification or only data(or include both)
my_key: 'Conf Name here'
}
};
fcm.send(message, function(err, response){
if (err) {
console.log("Something has gone wrong!"+err);
} else {
console.log("Successfully sent with response: ", response);
}
});
})
My first question is what should I do in the to field so that all the users in my app reciece the notification.
I would also like to take a look at correct and complete implementation of this concept with android code. If anyone has such code please share it here as it would help the future Firebase users who cannot understand the official docs like me.
Following is one approach using node-gcm (https://github.com/ToothlessGear/node-gcm)
var gcm = require('node-gcm');
var sender = new gcm.Sender(<sender_key>);
var message = new gcm.Message();
message.addNotification('title', title);
message.addNotification('body', body);
sender.send(message, { topic: "/topics/" + topic }, function (err, response) {
if (err) console.error(err);
else console.log(response);
});
Related
First I generated a FCM token and stored in firestore. After that I wrote a cloud functions to send notifications based on FCM token. and I deployed cloud functions it says successfully sent notifications with status ok. But it doesn't displays in mobile device. My Index.js is
'use strict';
const functions = require('firebase-functions');
const Firestore = require('#google-cloud/firestore');
const admin = require('firebase-admin');
const firestore = new Firestore();
const db = admin.firestore();
admin.initializeApp(functions.config().firebase);
exports.hellouser = functions.firestore
.document('users/{token}')
.onWrite(event =>{
var document = event.data.data();
console.log("tokens",document);
var token = ['cdNN0AbYKU0:APA91bEyL0zo3zwHZD8H43Vp7bxAfYgehlVI8LrKktPO2eGuByVDdioysIGxHe5wocwq8ynxRToJPpOve_M59YY_MIRbWLnF9AIgoTwJORXZbw6VBw7']// this is my FCM token.
if(
const payload = {
notification: {
title: "Message",
body: "hi hello",
sound: "default"
}
};
return admin.messaging().sendToDevice(token, payload).then((response)=> {
console.info("Successfully sent notification")
}).catch(function(error) {
console.warn("Error sending notification " , error)
});
});
How to send notifications based on the FCMtoken.
If it's the exact code you use then check syntax near if(. This may help you.Next write some code to go through your response object. Firebase may take your tokens and payload, process them and return 200 OK response but in the response you will have errors. Response has general structure like this: { results:
[ { //stuff related to one token },{ //stuff related to one token } ],
canonicalRegistrationTokenCount: 0,
failureCount: 1,
successCount: 0,
multicastId: SOME_LONG_NUMBER }Take in mind that response.results array has status of each message sent to token in the same order as tokens in your token array. You can see all posible errors in Firebase Documentation. If response.failureCount > 0 then no messages were sent and you should get corresponding error in response.results.Also learn about options variable. options.priority must be 'high' to guarantee fast message delivery. Maybe this will help.
I am using Ruby version 1.8.7.
I use this FCM gem https://github.com/spacialdb/fcm and want to send notification message to Android client app but it does not work.
In Controller:
fcm = FCM.new(FIREBASE_API_KEY, :timeout => 30)
options = {:data => {:message => "This is a FCM Topic Message!"}}
response = fcm.send_to_topic('global', options)
Class FCM:
require 'httparty'
require 'cgi'
require 'json'
class FCM
include HTTParty
base_uri 'https://fcm.googleapis.com/fcm'
default_timeout 30
format :json
attr_accessor :timeout, :api_key
def initialize(api_key, client_options = {})
#api_key = api_key
#client_options = client_options
end
def send_with_notification_key(notification_key, options = {})
body = { :to => notification_key }.merge(options)
params = {
:body => body.to_json,
:headers => {
'Authorization' => "key=#{#api_key}",
'Content-Type' => 'application/json'
}
}
response = self.class.post('/send', params.merge(#client_options))
response.parsed_response
end
def send_to_topic(topic, options = {})
if topic =~ /[a-zA-Z0-9\-_.~%]+/
send_with_notification_key('/topics/' + topic, options)
end
end
end
The server key is correct, because I can send notification successfully by PHP code.
The response output as below:
{"message_id"=>8885803884270587181}
Could anyone please to point out what wrong with the code.
Any help would be greatly appreciated.
According to the Firebase API documentation the response you get is the expected response for a successfully queued message.
The fact that you get back a message_id has this meaning:
The topic message ID when FCM has successfully received the request and will attempt to deliver to all subscribed devices.
It looks like your code is working, i.e. the problem must be somewhere else.
EDIT:
You are sending a data message. (Because no notification key, just a data key) Perhaps your client expects a notification message instead?
See the documentation for the distinction between those two message types.
You can try and just add a notification key to the request:
fcm = FCM.new(FIREBASE_API_KEY, :timeout => 30)
options = {:notification => "Test notification",
:data => {:message => "This is a FCM Topic Message!"}}
response = fcm.send_to_topic('global', options)
I have this problem before
try to add priority: "high" and notification: "your message"
in your FCM class instatiation options
I am not sure if this is due to changes in FCM itself but using the syntax from the gem's documentation or using the format from Daniel's answer did not work for me (Daniel's version gives an error response from FCM saying that notification must be a JSON object).
This is what worked for me:
fcm.send_to_topic(topic, notification: { body: "topic notification" })
Unfortunately the fcm library does not provide support to the rubies < 2.0. According to the git history of the repository that was the case already at the start of the project.
Try this
request = HTTParty.post('http://fcm.googleapis.com/fcm/send', :body => { "to" => "#{token}", "priority" => "high", "data" => { "title" =>title,"body"=>message,'massage_type'=>'text'}}.to_json, :headers => { 'Content-Type' => 'application/json', 'Authorization' => "key=#{server_token}" } )
I have a problem regarding my SNS Push Notifications. I have the following lambda code:
db.scan(params, function(err, data) {
if (err) {
console.log(err); // an error occurred
}
else {
data.Items.forEach(function(record) {
var receiverID = record.userDeviceToken.S;
var message = "You have a new invitation to the event";
var topic = "Friend's invitation";
var eventText = JSON.stringify(event);
console.log("Received event:", eventText);
var sns = new AWS.SNS();
var params = {
Message: message,
Subject: "Friend's invitation",
TargetArn: receiverID,
};
sns.publish(params, function(err, data) {
if (err) {
console.log('Failed to publish SNS message');
context.fail(err);
}
else {
console.log('SNS message published successfully');
context.succeed(data);
}
});
});
//context.succeed(data.Items); // data.Items
}
});
};
Now my goal is to get the "Subject" or "topic" sometimes, if it is possible. I cannot find it in documentation, and I need it to customize my notification title depending on the push message sent (I have few functions).
When I used sample amazon app I found this cound in Push Listener Service:
public static String getMessage(Bundle data) {
// If a push notification is sent as plain text, then the message appears in "default".
// Otherwise it's in the "message" for JSON format.
return data.containsKey("default") ? data.getString("default") : data.getString(
"message", "");
}
This works, but the "data" itself has the following data:
Bundle[{google.sent_time=1480364966070, google.message_id=0:1480364966079787%22269524f9fd7ecd, default=You have a new invitation to the event, collapse_key=do_not_collapse}]
Therefore, it is just providing some internal data and the "message" itself. I cannot access the topic.
My question is: how to get other variables in the Android code so I can use them further on? Can I add custom variables by myself through data bundle?
I have notifications in JSON format. I just wonder, whether the only way is to put the data I want in JSON format inside the message, and then read the message accordingly, or maybe I can attach the required data from lambda function to the push notification already?
I'm about to begin working on a recipe Android app for my college final project, and I want users to be able to add recipes to the database. However, I don't want the data to be added right away, but I'd like to receive a notification whenever someone wants to add a recipe, so I can confirm it myself. I'm using back{4}app by the way.
How can I do such a thing in a not-so-complicated way? I was thinking to create an admin account for myself in the app itself, but is there any way to send the notifications to said account? I also want to be able to confirm recipe addition with a simple "Confirm" button from within the app, so will this require me to create an additional class for pending recipes? Will I need an admin account in any case?
all this can be achieve by using cloud code.
Parse.cloud.define("addRecipe", function(request, response) {
const query = new Parse.Query("recipe");
query.set("name", "name");
query.save({
success function(result) {
response(result);
//call push notification function from client or from cloud code when the error is nil
},
error: function(result, error) {
response(error);
}
});
});
this is an example of push notifications using cloud code.
push notification are not allow anymore from the client due to secure reason.
you should be subscribe to this channel
Parse.Cloud.define("pushsample", function (request, response) {
Parse.Push.send({
channels: ["channelName"],
data: {
title: "Hello!",
message: "Hello from the Cloud Code",
}
}, {
success: function () {
// Push was successful
response.sucess("push sent");
},
error: function (error) {
// Push was unsucessful
response.sucess("error with push: " + error);
},
useMasterKey: true
});
});
you should also implement some logic to your app in order to display recipes confirm by admin.
var recipe = Parse.Object.extend("recipe");
var query = new Parse.Query(recipe);
query.equalTo("confirm", true);
query.find({
success: function(results) {
//it will display recipes confirmed
},
error: function(error) {
alert("Error: " + error.code + " " + error.message);
});
you should also setup a admin system in your app or a website
I am using parse for my application
I have one fragment on user which have to write article and save on parse but with not approve
when admin approve that user filed I want to send push notification automatically to that user with particular article is approved message
How can I implement this things..?
Parse.Cloud.afterSave("Data", function(request) {var dirtyKeys = request.object.dirtyKeys();for (var i = 0; i < dirtyKeys.length; ++i) {
var dirtyKey = dirtyKeys[i];
if (dirtyKey === "name") {
//Get value from Data Object
var username = request.object.get("name");
//Set push query
var pushQuery = new Parse.Query(Parse.Installation);
pushQuery.equalTo("name",username);
//Send Push message
Parse.Push.send({
where: pushQuery,
data: {
alert: "Name Updated",
sound: "default"
}
},{
success: function(){
response.success('true');
},
error: function (error) {
response.error(error);
}
});
return; } } response.success();});
If this is a matter of just hitting "approve", I would create a cloud code function for "Approve article" that is called by the admin tapping an approve button. This function sets the approve status and then calls a function (still in cloud code) for sending the push message to the user.
More on cloud code functions: https://parse.com/docs/cloudcode/guide#cloud-code-cloud-functionshttps://parse.com/docs/cloudcode/guide#cloud-code-cloud-functions
Alternatively the approve button can change status and save the document, and then an afterSave() function in cloud code can handle the push. This is less clear, though, since the afterSave() function will always be called when the record is saved, and it would need to check for status and only send push if the article has been approved.