I am able to send Push notifications using the code below but I am also required to associate "Conversion events" with the notification. This can be done through the console but I couldn't find how to do it with SDK.
var message = new Message()
{
Data = new Dictionary<string, string>()
{
{ "test1", "6165" },
{ "test2", "161" },
},
Notification =
{
Body = "",
Title = ""
},
Topic = topic,
};
// Send a message to the devices subscribed to the provided topic.
Task<string> response = FirebaseMessaging.DefaultInstance.SendAsync(message, true);
// Response is a message ID string.
response.Wait();
Console.WriteLine("Successfully sent message: " + response);
Related
I'm new to programming and I'm developing an app in which the user is suppose to get a notification 30 minutes before an event that's scheduled on the app. The schedule is saved in the firebase database and the device checks every 30 minutes to see if it's time to send an alert. If that condition becomes true, I want the device to send the notification so that the user will be alerted about the event. Every tutorial I saw only showed how to send notification through firebase itself. None of them covered how you can send them from the device.
I came across this code:
final postUrl = Uri.parse('https://fcm.googleapis.com/fcm/send');
final data = {
"registration_ids": tokens, //list of tokens
"collapse_key": "type_a",
"notification": {
"title": 'title',
"body": 'body',
},
"data": {
"data1": 'data 1', //data passed
}
};
final Map<String, String> headers = {
'content-type': 'application/json',
'Authorization': serverKey, //..................FCM server key
};
final response = await http.post(postUrl,
body: json.encode(data),
encoding: Encoding.getByName('utf-8'),
headers: headers);
if (response.statusCode == 200) {
print('test ok push CFM');
return true;
} else {
print(' CFM error');
print(response.statusCode);
return false;
}
}
But isn't this bad practice since your server key is exposed? Are there any better and safe methods to do this using flutter??
I think checking the firebase database every 30 minutes from the device is not a good decision.
You can use/write a firebase cloud function. Using a firebase cloud function you can watch any document/field and try to write notification trigger logic like if a event is before 30 minutes then this cloud function will throw a notification via firebase messaging.
See https://firebase.flutter.dev/docs/functions/overview/ for more information.
i am trying to handle group notifications in my react native project using firebase cloud messaging. notifications come correctly in foreground/background and when app is killed but i have problem to group my notifications. i used groupChannel as the documentation said but when notifications have been sent to device , the newer one replaces the old one.
here is what i send through postman:
{
"to": "my-token",
"priority":"high",
"data": {
"title": "my title",
"body": "Lorem",
"remote": true,
"sound":"default",
"priority":"high",
"groupId":"Group2",
"tag":"GroupTag"
}
}
here are my codes:
this.notificationListener = firebase.messaging().onMessage(async message=>{
console.log(message,'foreground')
const {body,title,sound,groupId,tag} = message.data;
const GroupChannelId = new firebase.notifications.Android.ChannelGroup(
groupId,
'Group')
firebase.notifications().android.createChannelGroup(GroupChannelId);
const localNotification = new firebase.notifications.Notification()
.setTitle(title)
.setBody(body)
.setData(message.data)
.setNotificationId(groupId)
.android.setGroup(groupId)
.android.setBigText(body)
.android.setVibrate([600,300,200,300,500])
.android.setAutoCancel(true)
.android.setChannelId(groupId)
.android.setGroupAlertBehaviour(firebase.notifications.Android.GroupAlert.Children)
.android.setPriority(firebase.notifications.Android.Priority.High);
const date = new Date();
date.setMinutes(date.getMinutes() + 1);
firebase.notifications().scheduleNotification(localNotification,{
fireDate:date.getTime()
})
firebase.notifications().displayNotification(localNotification);
})
I am using a webhook and c# to fulfill my logic within an Action.
I have subscribed to two intents, and have captured the "UpdateUserId".
Here is the notification payload
{
"customPushMessage": {
"target": {
"userId": "ABwppHFW6M9ASVqbKFBigM8N0mgssCJmPlwarmgzil_Nk_YsdZ1evzTAggEh0aEsctjOIYg2uHc8n7KfzNuHLuJoirXW",
"intent": "NotificationIntent",
"argument": {
"rawText": "Notification Argument Raw Text",
"textValue": "Notification Argument Text Value",
"name": "Notification Argument"
},
"locale": "en-US"
},
"userNotification": {
"title": "Notification Title",
"text": "Notification Text"
}
}
}
I am sending my notification using the following code blocks
private static async Task<string> GetAccessTokenFromJsonKeyAsync(string jsonKeyFilePath, params string[] scopes)
{
using (var stream = new FileStream(jsonKeyFilePath, FileMode.Open, FileAccess.Read))
{
return await GoogleCredential
.FromStream(stream) // Loads key file
.CreateScoped(scopes) // Gathers scopes requested
.UnderlyingCredential // Gets the credentials
.GetAccessTokenForRequestAsync(); // Gets the Access Token
}
}
public async Task<HttpResponseMessage> SendNotificationMessage(ProactiveMessage proactiveMessage)
{
try
{
var accessToken = await GetAccessTokenFromJsonKeyAsync("key.json", "https://www.googleapis.com/auth/actions.fulfillment.conversation");
var serialized = JsonConvert.SerializeObject(proactiveMessage);
var payload = "{\"customPushMessage\": " + serialized + "}";
// Wrap our JSON inside a StringContent which then can be used by the HttpClient class
var httpContent = new StringContent(payload, Encoding.UTF8, "application/json");
_httpClient.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", accessToken);
var httpResponseMessage = await _httpClient.PostAsync($"{_hostUrl}", httpContent);
Console.WriteLine(httpResponseMessage.IsSuccessStatusCode ? "Successfully sent notification message." : $"Failed to send notification message with {httpResponseMessage.StatusCode}.");
return httpResponseMessage;
}
catch (Exception ex)
{
Debug.WriteLine($"Google Assistant Service: Failed to send notification message with exception: {ex.Message}");
return new HttpResponseMessage(HttpStatusCode.BadRequest);
}
}
The method returns a 200 Response. However, a notification never shows up on my phone.
I am not sure what my next steps for debugging are.
Since notifications are stil not public, is this a common issue?
I had the same issue. I received 200 status code but no notifications arrived at the target device.
I tried it again in approximately 2 days and it worked with no problems and have been working ever since.
The only explanation I could come up with is that there is some configuration running in the background.
I am trying to make a POST request to a Firebase Notifications API using Vapor 1.5 and Firebase Legacy Protocol, but I get failure response.
response is JSON(node: Node.Node.object(["multicast_id":
Node.Node.number(5936281277445399934), "failure": Node.Node.number(0),
"canonical_ids": Node.Node.number(0), "results":
Node.Node.array([Node.Node.object(["message_id":
Node.Node.string("0:1527074314969790%c7ade8b9f9fd7ecd")])]),
"success": Node.Node.number(1)]))
EDIT
Making the request through POSTMan fails with error "The request was missing an Authentication Key (FCM Token)."
class FirebaseRequester {
let fcmLegacyServerKey = "AIzaSyDSuXXXXXXkCafTQay5_r8j3snvVos"
func sendNotification(payLoad: JSON) throws -> Response {
var response: Response?
do {
let responseFCM = try drop.client.post("https://fcm.googleapis.com/fcm/send",
headers: ["Content-Type":"application/json","Authorization": "key\(fcmLegacyServerKey)"],
query: [:],
body: payLoad.makeBody())
response = responseFCM
}catch let error {
let message = error.localizedDescription
logErr.prints(message: message)
throw Abort.custom(status: .badRequest, message: message)
}
guard let rsp = response?.json else {
let message = "no json received on line \(#line)"
drop.log.error(message)
logErr.prints(message: message)
throw Abort.custom(status: .badRequest, message: message)
}
print("rsp in json format is \(rsp)")
return response!
}//end of sendNotification()
}//end of class FirebaseRequester
//make another class here and initialize it with FirebaseRequester
//get data from Client App
// validate data
// finally, create the payLoad and call sendNotification(:)
//request should look like
{
"aps": {
"alert": "Breaking News!",
"sound": "default",
"link_url": "https://raywenderlich.com"
}
}
let fcmKeyToSendTo = "someDeviceTokenKeyReceivedFromClient_biHZNI-e9E53WEkCzrki"
let data = try Node(node: ["alert": "alert", "sound": "sound", "link_url": "https://www.someWebsite.com"])
var payLoadObj = try JSON(node: ["aps" : data])
payLoadObj["to"] = try JSON(node: fcmKeyToSendTo)
do {
let _ = try firebaseRequester.sendNotification(payLoad: payLoadObj)
}catch{
logErr.prints(message: error.localizedDescription)
}
let message = "notification Sent"
return try JSON(node:["success":message])
In sendNotification(payload:) I had a typo, I missed = after key. It should have been "key=\(fcmLegacyServerKey)"
In sendNotification(payload:), payLoad.makeBody should not be called, I should have just passed the JSON object payLoad as an argument to the .post request.
The JSON object of the notification was clearly badly formatted from the outset. The message type I wanted to send was notification, but I was passing in a key named aps. I should have passed key notification as shown below.
.
class FirebaseRequester {
let fcmLegacyServerKey = "AIzaSy....vVos"
func sendNotification(payLoad: JSON) throws -> Response {
var response: Response?
do {
let responseFCM = try drop.client.post("https://fcm.googleapis.com/fcm/send",
headers: ["Content-Type":"application/json","Authorization": "key=\(fcmLegacyServerKey)"],
query: [:],
body: payLoad
response = responseFCM
}catch let error {
let message = error.localizedDescription
logErr.prints(message: message)
throw Abort.custom(status: .badRequest, message: message)
}
guard let rsp = response?.json else {
let message = "no json received on line \(#line)"
drop.log.error(message)
logErr.prints(message: message)
throw Abort.custom(status: .badRequest, message: message)
}
return response!
}//end of sendNotification()
}//end of class FirebaseRequester
class TestRouteNow {
let firebaseRequester: FirebaseRequester
init(firebaseRequester: FirebaseRequester) {
self.firebaseRequester = firebaseRequester
}
func addRoutes(drop: Droplet) {
drop.post("test", "notif", handler: postNotification)
}
func postNotification(request: Request) throws -> ResponseRepresentable {
let fcmDevice = "someDeviceTokenReceivedFromClientApp"
let data = try Node(node: ["title": "title","body": "body", "sound": "default", "badge":"60"])
var payLoadObj = try JSON(node: ["notification": data])
payLoadObj["to"] = try JSON(node: fcmDevice)
do {
let _ = try firebaseRequester.sendNotification(payLoad: payLoadObj)
}catch{
logErr.prints(message: error.localizedDescription)
}
let message = "notification Sent"
return try JSON(node:["success":message])
}
}//end of class
// request body
{
"to" : "cQDtm_someDeviceTokenReceivedFromClient",
"priority":"high",
"notification": {
"title":"Booking Rescheduled",
"body": "Cancelled Booking 7830593, for Mon, 12 March",
"sound":"default",
"badge": "100"
}
}
I am using the phonegap-plugin-push plugin to do Push Notifications in an Ionic 2 Chat App.
I've implemented it according to the documentation, and it works, but only on the same device. i.e. it sends a notification to the phone if you supply its device token.
My issue is for a chat app, I need a PubSub model. So that a user can publish to a topic and another user can subscribe to that topic even if they are on different decices.
Looking at the documentation, it seems to be possible. See android.topics and ios.topics.
android.topics array [] Optional. If the array contains one or more
strings each string will be used to subscribe to a GcmPubSub topic.
So I try the following:
Javascript Client:
publish
let push = Push.init({
android: {
senderID: "xxxxxxxx",
topics: ['foo']
},
ios: {
alert: "true",
badge: false,
sound: "true",
topics: ['foo']
},
windows: {}
});
push.on('registration', (data) => {
// call the Java Server
let promise: Promise<string> = this.notificationService.push(data.registrationId, 'This is a test message from Ionic Chat');
promise.then((data) => {
});
});
Java Server:
try {
System.out.println("NotificationService: device_token: "+device_token);
logger.info("NotificationService: device_token: "+device_token);
// Prepare JSON containing the GCM message content. What to send and where to send.
JSONObject jGcmData = new JSONObject();
JSONObject jData = new JSONObject();
jData.put("title", "This is title");
jData.put("message", message);
jGcmData.put("to", device_token); // <===== is this the problem???? it is the data.registrationId from the client
// What to send in GCM message.
jGcmData.put("data", jData);
// Create connection to send GCM Message request.
URL url = new URL("https://gcm-http.googleapis.com/gcm/send");
HttpURLConnection conn = (HttpURLConnection) url.openConnection();
conn.setRequestProperty("Authorization", "key=" + API_KEY);
conn.setRequestProperty("Content-Type", "application/json");
conn.setRequestMethod("POST");
conn.setDoOutput(true);
// Send GCM message content.
OutputStream outputStream = conn.getOutputStream();
outputStream.write(jGcmData.toString().getBytes());
} catch (Exception e) {
e.printStackTrace();
}
Javascript Client:
Subscribe
let push = Push.init({
android: {
senderID: "xxxxxxxx",
topics: ['foo']
},
ios: {
alert: "true",
badge: false,
sound: "true",
topics: ['foo']
},
windows: {}
});
push.on('notification', (data) => {
});
It works on the same device, but it doesn't work if the publisher and subscriber are on different devices.
I think the problem may be that even though another user is subscribed to the topic I publish to, it is still only publishing to the data.registrationId (Device Token).
See the following line on the Java Server:
jGcmData.put("to", device_token);
Question
Does anyone know how to make it send to all subscribers on that topic?
I think the answer is here:
"to": "/topics/foo-bar",
But how should this be formatted for multiple topics? (that's just one topic foo-bar)
Need to Change the Java Server to send to the topic instead of the device:
jGcmData.put("to", "/topics/"+topics);
see: https://developers.google.com/cloud-messaging/