I have an application that I made with Flutter. I am trying to write a method for users to add each other as friends in my application, but before I do this, I want to send push notifications from one device to the other. Actually, I think if I start, I can solve the rest with my own algorithm.
Ways I've tried:
installed node.js
from project terminal: firebase login
firebase init
functions file created and exists in my project
i have index.ts file
I get unique token for each device when app opened.
I want to put a simple notification sending code in the index.ts file, but I couldn't. And this notification should work from one device to another.
Here is simple solution to send device to device notification.
First create json formatted parameters like below
var params = {
"to": "device token",
"notification": {
"title": "Notification Title",
"body": "Notification Message",
"sound": "default",
},
"data": {
"customId": "01",
"badge": 0,
"alert": "Alert"
}
};
Then var url = 'https://fcm.googleapis.com/fcm/send'; call as api.
Get response like below code
var response = await http.post(url,
headers: {
"Authorization": "key= Web server Key over here",
"Content-Type": "application/json"
},body: json.encode(params)
);
if (response.statusCode == 200) {
Map<String, dynamic> map = json.decode(response.body);
print("fcm.google: "+map.toString());
}
else {
Map<String, dynamic> error = jsonDecode(response.body);
print("fcm.google: "+error.toString());
}
Related
I checked the Open application on notification click in OneSignal and OneSignal Push Notification Click to open actiivty but still not answers yet. So, I'm building a news app and integrating it with OneSignal, I'm able to receive the notification and when I clicking on it I'm getting the below JSON code
OneSignal.shared.setNotificationOpenedHandler((OSNotificationOpenedResult result) {
this.setState(() {
print(
"Opened notification:
${result.notification.jsonRepresentation().replaceAll("\\n","\n")}");
});
});
JSON Response
Opened notification: {
"payload": "{
"google.delivered_priority": "normal",
"google.sent_time": 1561415365754,
"google.ttl": 259200,
"google.original_priority": "normal",
"custom": "{"a":{"id":"43682"},"i":"b0f4ef57-9556-4163-9e5c- fbcea08b4ce8"}",
"from": "800826514709",
"alert": "Test Alert",
"title": "Test Title",
"google.message_id": "0:1561415365759264%e192c215f9fd7ecd",
"notificationId": -655945385
I/flutter (30970): }",
"displayType": 2,
"shown": true,
"appInFocus": true,
"silent": null
I/flutter (30970): }
And the below code to capture the payload keys
print(result.notification.payload.jsonRepresentation());
JSON Response
{
"google.delivered_priority": "normal",
"google.sent_time": 1561415365754,
"google.ttl": 259200,
"google.original_priority": "normal",
"custom": "{"rec":{"id":"43682"},"i":"b0f4ef57-9556-4163-9e5c-fbcea08b4ce8"}",
"from": "800826514709",
"alert": "Test Alert",
"title": "Test Title",
"google.message_id": "0:1561415365759264%e192c215f9fd7ecd",
"notificationId": -655945385
}
My Question is how do I read the Key "notificationId" and "custom", I tried something like below but getting null
Map<String, dynamic> data =
json.decode(result.notification.jsonRepresentation());
print(data['custom']);
i have this solution for you.
var notificationId = result.notification.payload.rawPayload["notificationId"];
Map<String, dynamic> custom = result.notification.payload.additionalData;
Good luck :)
You can get additional data with this:
OneSignal.shared.setNotificationOpenedHandler((openedResult) async{
var additionalData = openedResult.notification.payload.additionalData;
if(additionalData != null){
if(additionalData.containsKey("myKey")){
var myValue= additionalData["myKey"];
}
}
});
I'm creating a chat application and i want to use fcm to send notification if the person has a new message, but i don't know how to proceed. All the tutorials i found use to send the message from firebase. But i want to send it automatically when there is a new message for the person
A possible workaround if you use firebase should be like this:
You need to store each firebase FCM token for a specific user (need to take in account here that a user can log in at the same time on his account from multiple devices) so you can store the userId and his deviceUniqueId on flutter you can get it from device_info https://pub.dev/packages/device_info:
String identifier;
final DeviceInfoPlugin deviceInfoPlugin = new DeviceInfoPlugin();
try {
if (Platform.isAndroid) {
var build = await deviceInfoPlugin.androidInfo;
identifier = build.id.toString();
} else if (Platform.isIOS) {
var data = await deviceInfoPlugin.iosInfo;
identifier = data.identifierForVendor;//UUID for iOS
}
} on PlatformException {
print('Failed to get platform version');
}
and after that to get the unique CFM token that Firebase provide for each device, you can get it using Firebase firebase_messaging plugin (https://pub.dev/packages/firebase_messaging) getToken() and insert the token to firestore (or an other database you want to store it)
FirebaseMessaging firebaseMessaging = new FirebaseMessaging();
firebaseMessaging.requestNotificationPermissions(
const IosNotificationSettings(sound: true, badge: true, alert: true));
firebaseMessaging.onIosSettingsRegistered
.listen((IosNotificationSettings settings) {
print("Settings registered: $settings");
});
firebaseMessaging.getToken().then((token){
print('--- Firebase toke here ---');
Firestore.instance.collection(constant.userID).document(identifier).setData({ 'token': token});
print(token);
});
After that you can insert one or more FCM token connected to multiple device for one user. 1 user ... n devices , 1 device ... 1 unique token to get push notifications from Firebase.
send it automatically when there is a new message for the person : now you need to call the Firestore API(is very fast indeed but need to be careful about the plan limit that you are using here) or another API call if you store the token to another db, in order to get the token/tokens for each user and send the push notifications.
To send the push notification from flutter you can use a Future async function.
P.s: I'm passing as argument a List here in order to use "registration_ids" instead of "to" and send the push notification to multiple tokens if the user has been logged in on multiple devices.
Future<bool> callOnFcmApiSendPushNotifications(List <String> userToken) async {
final postUrl = 'https://fcm.googleapis.com/fcm/send';
final data = {
"registration_ids" : userToken,
"collapse_key" : "type_a",
"notification" : {
"title": 'NewTextTitle',
"body" : 'NewTextBody',
}
};
final headers = {
'content-type': 'application/json',
'Authorization': constant.firebaseTokenAPIFCM // 'key=YOUR_SERVER_KEY'
};
final response = await http.post(postUrl,
body: json.encode(data),
encoding: Encoding.getByName('utf-8'),
headers: headers);
if (response.statusCode == 200) {
// on success do sth
print('test ok push CFM');
return true;
} else {
print(' CFM error');
// on failure do sth
return false;
}
}
You can also check the post call from postman in order to make some tests. POST request
On Headers add the:
key Authorization with value key=AAAAO........ // Project Overview -> Cloud Messaging -> Server Key
key Content-Type with value application/json
And on the body add
{
"registration_ids" :[ "userUniqueToken1", "userUniqueToken2",... ],
"collapse_key" : "type_a",
"notification" : {
"body" : "Test post",
"title": "Push notifications E"
}
}
"registration_ids" to send it to multiple tokens (same user logged in to more than on device at the same time)
"to" in order to send it to a single token (one device per user / or update always the user token that is connected with his device and have 1 token ... 1 user)
I'm making an edit to the response, in order to add that is very important to add the FCM Server Key on a trusted environment or server!
I'll list here a few related questions which I have participated with answers. I guess you'll find a lot of relevant info on using firebase cloud messaging (FCM) in a chat app.
Is FCM the only way to build a chat app ?
Suggested approach to use FCM in a chat app
Is using topics a better solution then using the fcmToken in a chat app?
Problems with FCM onMessage while app is in background
Problem: after logoff, user continues to receive notifications
Good luck!
//Notification Sending Side Using Dio flutter Library to make http post request
static Future<void> sendNotification(receiver,msg)async{
var token = await getToken(receiver);
print('token : $token');
final data = {
"notification": {"body": "Accept Ride Request", "title": "This is Ride Request"},
"priority": "high",
"data": {
"click_action": "FLUTTER_NOTIFICATION_CLICK",
"id": "1",
"status": "done"
},
"to": "$token"
};
final headers = {
'content-type': 'application/json',
'Authorization': 'key=AAAAY2mZqb4:APA91bH38d3b4mgc4YpVJ0eBgDez1jxEzCNTq1Re6sJQNZ2OJvyvlZJYx7ZASIrAj1DnSfVJL-29qsyPX6u8MyakmzlY-MRZeXOodkIdYoWgwvPVhNhJmfrTC6ZC2wG7lcmgXElA6E09'
};
BaseOptions options = new BaseOptions(
connectTimeout: 5000,
receiveTimeout: 3000,
headers: headers,
);
try {
final response = await Dio(options).post(postUrl,
data: data);
if (response.statusCode == 200) {
Fluttertoast.showToast(msg: 'Request Sent To Driver');
} else {
print('notification sending failed');
// on failure do sth
}
}
catch(e){
print('exception $e');
}
}
static Future<String> getToken(userId)async{
final Firestore _db = Firestore.instance;
var token;
await _db.collection('users')
.document(userId)
.collection('tokens').getDocuments().then((snapshot){
snapshot.documents.forEach((doc){
token = doc.documentID;
});
});
return token;
}
//Now Receiving End
class _LoginPageState extends State<LoginPage>
with SingleTickerProviderStateMixin {
final Firestore _db = Firestore.instance;
final FirebaseMessaging _fcm = FirebaseMessaging();
StreamSubscription iosSubscription;
//this code will go inside intiState function
if (Platform.isIOS) {
iosSubscription = _fcm.onIosSettingsRegistered.listen((data) {
// save the token OR subscribe to a topic here
});
_fcm.requestNotificationPermissions(IosNotificationSettings());
}
_fcm.configure(
onMessage: (Map<String, dynamic> message) async {
print("onMessage: $message");
showDialog(
context: context,
builder: (context) => AlertDialog(
content: ListTile(
title: Text(message['notification']['title']),
subtitle: Text(message['notification']['body']),
),
actions: <Widget>[
FlatButton(
child: Text('Ok'),
onPressed: () => Navigator.of(context).pop(),
),
],
),
);
},
onLaunch: (Map<String, dynamic> message) async {
print("onLaunch: $message");
// TODO optional
},
onResume: (Map<String, dynamic> message) async {
print("onResume: $message");
// TODO optional
},
);
//saving token while signing in or signing up
_saveDeviceToken(uid) async {
// FirebaseUser user = await _auth.currentUser();
// Get the token for this device
String fcmToken = await _fcm.getToken();
// Save it to Firestore
if (fcmToken != null) {
var tokens = _db
.collection('users')
.document(uid)
.collection('tokens')
.document(fcmToken);
await tokens.setData({
'token': fcmToken,
'createdAt': FieldValue.serverTimestamp(), // optional
'platform': Platform.operatingSystem // optional
});
}
}
I'm trying to send a notification to a single device. Since I can't install an android emulator on my computer, I tested my program by installing apk on my phone, which prevents me from seeing the console messages. I get a token with the getToken () process, then I use this token as follows:
sendNotification()
{
let body = {
"notification":{
"title":"New Notification has arrived",
"body":"Notification Body",
"sound":"default",
"click_action":"FCM_PLUGIN_ACTIVITY",
"icon":"fcm_push_icon"
},
"data":{
"param1":"value1",
"param2":"value2"
},
"to":toKey,
}
let options = new HttpHeaders().set('Content-Type','application/json');
this.http.post("https://fcm.googleapis.com/fcm/send",body,{
headers: options.set('Authorization', key),
})
.subscribe((customer) => {
console.log(customer);
},
(err) => {console.log(err)});
}
This results in an error named "InvalidRegistration" in the console.
i am coding an Api Rest in rails 5, using gem 'fcm' to send notifications. I have already configure firebase in my android app and I can send notifications successfully from the Firebase console, but from my rails api i cannot receive the notificacion in my device, this is my code:
this is my rails controller:
class AccionesController < ApplicationController
def enviar
require 'fcm'
fcm = FCM.new("AAAAlBfTsV4:AheregoesmySERVEKEYsXXm-vQGfMjVuo8TpYrApHsnGU4ZasdfajsdfñalUtf26LeND4U4lXFZZplpzJjTWoiisWP-Esl5afCSTmiDI9y5gP6OObqY76NVcOn9ceaIUGMZ")
# fcm = FCM.new("my_server_key", timeout: 3)
registration_ids= [params[:devicetoken]] # an array of one or more client registration tokens
options = {data: {score: "mynewscore"},
notification: {
title: "Message Title",
body: "Hi, Worked perfectly",
icon: "myicon"}
,collapse_key: "testeando desde rails", priority: "high"}
response = fcm.send(registration_ids, options)
render json: response
end
def noti_params
params.permit(:devicetoken)
end
end
I execute from Postman this is the route that execute the controller:
http://localhost:3000/acciones/enviar?here goes the device token as parameter
And, here is the response:
{"body":"{\"multicast_id\":5276983113254623155,\"success\":1,\"failure\":0,\"canonical_ids\":0,\"results\":[{\"message_id\":\"0:1502991819420287%2293308c2293308c\"}]}","headers":{"content-type":["application/json;
charset=UTF-8"],"date":["Thu, 17 Aug 2017 17:43:39
GMT"],"expires":["Thu, 17 Aug 2017 17:43:39
GMT"],"cache-control":["private,
max-age=0"],"x-content-type-options":["nosniff"],"x-frame-options":["SAMEORIGIN"],"x-xss-protection":["1;
mode=block"],"server":["GSE"],"alt-svc":["quic=\":443\"; ma=2592000;
v=\"39,38,37,35\""],"accept-ranges":["none"],"vary":["Accept-Encoding"],"connection":["close"]},"status_code":200,"response":"success","canonical_ids":[],"not_registered_ids":[]}
the response shows success: 1 and status code: 200 but the notification never reaches the device,and the firebase console does not show the message.
Am I missing something?
please help?
or is there another way or ruby gem to send notification with a clear example?
any suggestions are welcome... thanks in advance
Instead of using fcm gem, you can also use RestClient gem. The usage for fcm notifications is as follow.One thing to note is if the payload is passing using ".to_json", the header content type also must be specified as json. Hope this help.
def self.send_noti(device_token)
options = data().merge ({"to": "#{device_token}"})
RestClient.post("https://fcm.googleapis.com/fcm/send", options.to_json, headers={'Content-Type' => 'application/json','Authorization' => "key=#{ENV['fcm_token']}"})
end
def self.data()
options = {
"notification": {
"body": "Your noti body",
"title": "Your noti title"
},
"data": {
"d1": "Your data" #can be any, d1, status or whatever
}
}
end
rest-client gem
fcm_client = FCM.new(your_firebase_key)
registration_ids= [user_device_token]
options = {
priority: 'high',
data: {
message: "Hai",
location: location
},
notification: {
body: "Hai",
location: "location",
sound: 'default'
}
}
fcm_client.send(registration_ids, options)
end
end
try this message options because the error should be your notification syntax.
options = {
priority: 'high',
data: {
message: "Hai",
location: location
},
notification: {
body: "Hai",
location: "location",
sound: 'default'
}
}
I am trying to have a previous push notification stack with the new one or replace it in the system tray for android.
I am not sure how to do this as the push notification is sending back both data and notification objects, and from what I understand the notification goes directly to the system tray. If so how do I stop the notification from appearing independently. Some users would get 5-10 notifications and it would keep pushing up.
EDIT:
I tried collapse_key but it still does not replace prior notifications with the same key... am I doing it wrong somehow here?
method: 'POST',
uri: 'https://gcm-http.googleapis.com/gcm/send',
headers: {
'Content-Type': 'application/json',
'Authorization': authorize //GOOGLE API KEY
},
body: JSON.stringify({
"registration_ids": [otherUserResult.reg_id],
"collapse_key": "follow",
"data": {
"notifyToUserId": to,
"notifyFromId": from,
"notifyMsg": msg,
"notifyItemPicture": itemPic,
"notifyItemName": itemName,
"notifyFromName": fromName,
"notifyType": type,
"dateNotified": dateNotified
},
"notification": {
"title": fromName,
"body": notifyMsg,
"icon" : "ic_pushnotify"
},
"priority": "high",
"content_available": true
For me worked when I included in my 'notification' 2 lines:
collapse_key: 'your_app_unique_string',
tag: 'your_app_unique_string'
So the full code would be:
var payload = {notification: {
title: "Mensaje de "+message.name,
body: message.text,
sound: "default",
collapse_key: 'charlero',
tag: 'charlero'
}
};