Firebase Cloud Messaging Notification Parsing in Android - android

I need to parse the notification body as a HashMap but the notification always displayed as a JSON string instead of the parsed message. Any ideas why?[Image of the Android notification received] (https://i.stack.imgur.com/IQIPb.jpg)
override fun onMessageReceived(message: RemoteMessage) {
super.onMessageReceived(message)
Log.i("FirebaseService ", "Message :: $message")
val title = message.notification!!.title
val body = message.notification!!.body
Log.i(TAG, "Messaging Service $body")
val notificationBody: HashMap<String, String> = Gson().fromJson(body, HashMap::class.java) as HashMap<String, String>
val messageBody = notificationBody["message"]
val rideId = notificationBody["rideId"]
if(notificationBody["type"] == "TRACK"){
showNotification(title!!, messageBody!!)
}else{
// Something else
}
}
I have tried to parse the remote message using the GSON library, but the notification always return the full body

I finally found the answer on another stack overflow question:
Retrieve notification values from a notification in system tray android firebase FCM
The onMessageReceived function is not triggered in the background, the system tray handles the notification, so the notification data was not parsed.
Now I need to handle the notification in the launcher event when the notification is triggered from the background.

Related

I'm not getting Push Notification when new message send to user And app is in Background

I'm making chat application trying to get push notification when new message received to user from another when app is in background using send notifications between Android devices using Firebase Database, Cloud Messaging and Node.js.
I'm following this blog.Here's
[https://firebase.googleblog.com/2016/08/sending-notifications-between-android.html]
and below is my code which I tried.
#Override
public void onClick(View view) {
if (view.getId() == R.id.btnSend) {
String content = editWriteMessage.getText().toString().trim();
if (content.length() > 0) {
editWriteMessage.setText("");
Message newMessage = new Message();
newMessage.text = content;
newMessage.idSender = StaticConfig.UID;
newMessage.idReceiver = roomId;
newMessage.timestamp = System.currentTimeMillis();
FirebaseDatabase.getInstance().getReference().child("message/" + roomId).push().setValue(newMessage);
sendNotificationToUser(newMessage.idReceiver,newMessage.text);
}
}
}
public void sendNotificationToUser(String user, String message) {
Map notification = new HashMap<>();
notification.put("username", user);
notification.put("message", message);
FirebaseDatabase.getInstance().getReference().child("notificationRequests").push().setValue(notification);
}
By using above codes the username and message is getting saved in real time database in notificationRequests.
And I really don't have idea that how can the push notification is received by this line of code.
FirebaseMessaging.getInstance().subscribeToTopic("user_"+username);
And the most important where do i need to put the above code to make it work.
and also I have created the bucket to host my node.js file.
thanks in advance.
EDIT: I misunderstood your problem. Make sure that firebase messaging service is in your manifest.xml file.
Original:
Use the functions.database.ref().onCreate() method. Inside the ref() parameters put the path to your notification requests.
Here's some base code in TypeScript.
export const notificationListener = functions.database
.ref('/NotificationRequests/{notification}').onCreate((snapshot, context) =>
{
try {
admin.initializeApp();
} catch (e) {
}
//Code to send notification here
return admin.database().ref('/NotificationRequests/' + context.params.notification)
}
)
The information you need for the notification is located under snapshot.child('your path here').
See why and how this works

PubNub Push Notification sends incorrect data on Android

Let me go straight to the point, with Firebase Cloud Messaging and Android Oreo there have been some major changes when it comes to using their APIs.
I have entered my Firebase Server Api Key in the PubNub Console, push notification works absolutely fine on the Firebase console, but when publishing notification with PubNub, remoteMessage.toString gives => com.google.firebase.messaging.RemoteMessage#ffe9xxx in the OnMessageReceived function.
I am publishing something like this
JsonObject payload = new JsonObject();
JsonObject androidData = new JsonObject();
androidData.addProperty("contentText","test content");
androidData.addProperty("contentTitle","Title");
JsonObject notification = new JsonObject();
notification.add("notification",androidData);
JsonObject data = new JsonObject();
data.add("data", notification);
payload.add("pn_gcm", data);
in
PubNubObject.publish()
.message(payload)
etc..
Any idea why is this happening?
Thank you in advance.
Code on the receiving end
There is a class which extends FirebaseMessagingService, codes for OnMessageReceived function:
if (remoteMessage.getNotification() != null) {
//for testing firebase notification
Log.d(TAG, "Message Notification
Body:"+remoteMessage.getNotification().getBody());
} else {
//for anything else, I wanted to see what was coming from the server
//this is where I am getting the message when using PubNub notification
Log.d(TAG, "onMessageReceived: remoteMessage to
str:"+remoteMessage.toString() );
}
Android getData vs getNotification API
You are nesting the notification key/value inside of the data key and just need to use the API, remoteMessage.getData() instead of remoteMessage.getNotification().
If notification key was at the top level, it would work. See Android docs here.
Instead of this:
{
"pn_gcm": {
"data": {
"notification": {
"contentText": "test content",
"contentTitle": "Title"
}
}
}
}
This if switing to remoteMessage.getData():
{
"pn_gcm": {
"data": {
"contentText": "test content",
"contentTitle": "Title"
}
}
}
Or this if sticking with remoteMessage.getNotification():
{
"pn_gcm": {
"notification": {
"contentText": "test content",
"contentTitle": "Title"
}
}
}
}
PubNub basically just looks for the pn_gcm in the message payload when it is published and grabs whatever is inside of it and passes that directly to Google's FCM service for the devices that are registered (with PubNub) for that channel to receive GCM (FCM).
If the data is not formatted properly we would receive an error back from FCM which should be reported on the channel's -pndebug channel (assuming pn_debug:true was included in the published message payload).
For full details on troubleshooting FCM (GCM) or APONS issues with PubNub, please review How can I troubleshoot my push notification issues?

Need to push Notification only to Recipient's device not the Sender's

I am really stuck and want to push notification only to specific user using Firebase. I know the FCM method and have got the token. But this tutorial or other tutorials that I've followed are making me send push notification to both users including the sender. I just want to get notification on Recipient Device. Its been a long day , I've been working on this problem.
Looking for some key or UID of the Recipient now. Is it to be fetched from token that I have : FirebaseInstanceId.getInstance().getToken();
Update : I am not able to store and retrieve token (device token) and other children and also am able to log the message in firebase "Functions" tab , but still not able to push the notification to the device . I am testing it on emulator .Should I test it on real device ?
My Node.js code:
const functions = require('firebase-functions');
const admin = require('firebase-admin');
admin.initializeApp(functions.config().firebase);
var rootRef =
functions.database.ref('/notifications/{user_id}/{notification_id}');
exports.sendNotification = rootRef.onWrite(event => {
const user_id = event.params.user_id;
const notification_id = event.params.notification_id;
var request = event.data.val();
var payload = {
data: {
title : "New Message from ",
body: "userName has sent you message",
icon: "default",
}
};
console.log('We have a notification for device token: ', user_id );
console.log('Checking if getting inside the node -- ', request.user );
admin.messaging().sendToDevice(user_id, payload)
.then(function(response){
console.log('This was the notification Feature',response);
})
.catch(function(error){
console.log('Error sending message ',error);
})
})
MyFirebaseMEssagingService.java
public class MyFirebaseMessagingService extends FirebaseMessagingService
{
private static final String TAG = "FCM Service";
#Override
public void onMessageReceived(RemoteMessage remoteMessage) {
// TODO: Handle FCM messages here.
// If the application is in the foreground handle both data and
notification messages here.
// Also if you intend on generating your own notifications as a result
of a received FCM
// message, here is where that should be initiated.
//remoteMessage.getNotification().getBody());
if(remoteMessage.getNotification()!=null){
Map<String,String> payload = remoteMessage.getData();
// String title =
remoteMessage.getNotification().getTitle();
// String message =
remoteMessage.getNotification().getBody();
// Log.d(TAG, "Message Notification Title : " + title);
// Log.d(TAG, "Message Notification Body: " + message);
System.out.println("Messaging Service : Title - " + payload.get("title")
+ " , body - " + payload.get("body"));
sendNotification(payload);
}
}
#Override
public void onDeletedMessages(){
}
private void sendNotification(Map<String,String> payload){
NotificationCompat.Builder builder = new
NotificationCompat.Builder(this);
builder.setSmallIcon(R.mipmap.ic_launcher);
builder.setContentTitle("Firebase Push
Notification"+payload.get("title"));
builder.setContentText("Notification Text : "+ payload.get("body"));
Intent intent = new Intent(this, ChatWindow.class);
TaskStackBuilder stackBuilder = TaskStackBuilder.create(this);
stackBuilder.addNextIntent(intent);
PendingIntent pendingIntent =
stackBuilder.getPendingIntent(0,PendingIntent.FLAG_UPDATE_CURRENT);
builder.setContentIntent(pendingIntent);
NotificationManager notificationManager = (NotificationManager)
getSystemService(Context.NOTIFICATION_SERVICE);
notificationManager.notify(0, builder.build());
}
}
FirebaseIDService.java:
public class FirebaseIDService extends FirebaseInstanceIdService {
private static final String TAG = "FirebaseIDService";
#Override
public void onTokenRefresh() {
// Get updated InstanceID token.
String refreshedToken = FirebaseInstanceId.getInstance().getToken();
Log.d(TAG, "Refreshed token: " + refreshedToken);
DatabaseReference firebase ;//= new Firebase("https://materialtabs-
b5734.firebaseio.com//messages");
firebase =
FirebaseDatabase.getInstance().getReferenceFromUrl("https://materialtabs-
b5734.firebaseio.com//notifications/");
// TODO: Implement this method to send any registration to your app's
servers.
sendRegistrationToServer(refreshedToken);
}
/**
* Persist token to third-party servers.
*
* Modify this method to associate the user's FCM InstanceID token with any
server-side account
* maintained by your application.
*
* #param token The new token.
*/
private void sendRegistrationToServer(String token) {
// Add custom implementation, as needed.
System.out.println("Reading Token : "+ token);
}
}
And I am starting my 'MyFirebaseMessagingService.java' inside my MainActivity file in "onCreate()"
as "startService(new Intent(this, MyFirebaseMessagingService.class));"
Please help me. I think I am missing some minor details or it could be major, not sure !
For that, you need to store the firebase token of the recipient's device and then whenever you want to send the notification to the recipient you have to retrieve the token of the recipient's from the database and then you can send the notification using that token to the only recipient.

How to initialize a RemoteMessage object with a Json file?

I am dealing with FCM messages and I have the following function:
public void onMessageReceived(final RemoteMessage remoteMessage)
{
final Map<String, String> data = remoteMessage.getData();
//...
}
For testing purposes, I have a Json file containing data- and I want to send that Json file from my test method to onMessagereceived() . Hence I need to initialize a RemoteMessage object with the Json file and pass this RemoteMessage object to the function. How do I initialize this?
My JSON file:
{
"data": {
"id" : "4422",
"type" : "1",
"imageUrl" : "https://image.freepik.com/free-vector/android-boot-logo_634639.jpg",
"smallTitle" : "DoJMA v2",
"smallSubTitle" : "Update now from Google Play Store",
"ticker" : "New update for DoJMA",
"contentInfo" : "",
"link" : "https://photo2.tinhte.vn/data/avatars/l/1885/1885712.jpg?1402763583",
"className" : "HomeActivity",
"page" : "2",
"bigTitle" : "DoJMA Android app version 2 released!",
"bigSubTitle" : "Hi folks! New DoJMA update is here! Major redesigning and improvements! This app was made by the Mobile App Club.They work really hard man...and get good products",
"bigSummaryText" : "Update now"
},
"registration_ids": ["dQYmpLUACXQ:APA91bGl-NoIMJ2_DcctF5-OA8ghyWuyrMfsz3uhlj1BySl6axkAsmv5y_7YGfpQQJ2E0lP_fTcxpHpZdkJzY1tbcWA36e78ooxC_b0a1PAank9gFIAUHVZkHKmZT70MPZosCgvRlVfq","dfLXnRI36qY:APA91bFyjLblijVIjGLCGWVeB1B0z5j_3TYqRytJ-8hvuUESpDlX59gWF3hU-I-kA4VrRCPpEVFWl18ZarnPjqxxtZgFkVxoLr77HRex27VN7Mh3xupWykmKq_nnVIlVzrODKwKI7ktM"]
}
you can test using Postman For Single User.
Send a notification with a JSON payload
URL: https://fcm.googleapis.com/fcm/send
Headers:
Authorization: key=<your-api-key>
Content-Type: application/json
Body (click on the 'raw' tab):
{
"to": "dQYmpLUACXQ:APA91bGl-NoIMJ2_DcctF5-OA8ghyWuyrMfsz3uhlj1BySl6axkAsmv5y_7YGfpQQJ2E0lP_fTcxpHpZdkJzY1tbcWA36e78ooxC_b0a1PAank9gFIAUHVZkHKmZT70MPZosCgvRlVfq",
"data": {
"id": "4422",
"type": "1",
"imageUrl": "https://image.freepik.com/free-vector/android-boot-logo_634639.jpg",
"smallTitle": "DoJMA v2",
"smallSubTitle": "Update now from Google Play Store",
"ticker": "New update for DoJMA",
"contentInfo": "",
"link": "https://photo2.tinhte.vn/data/avatars/l/1885/1885712.jpg?1402763583",
"className": "HomeActivity",
"page": "2",
"bigTitle": "DoJMA Android app version 2 released!",
"bigSubTitle": "Hi folks! New DoJMA update is here! Major redesigning and improvements! This app was made by the Mobile App Club.They work really hard man...and get good products",
"bigSummaryText": "Update now"
}
}
Source : https://firebase.google.com/docs/cloud-messaging/concept-options
TL;DR: Initializing a RemoteMessage object is not possible.
Attempting to access initialize a RemoteMessage from your own class would return an error:
'RemoteMessage(android.os.Bundle)' is not public in 'com.google.firebase.messaging.RemoteMessage'. Cannot be accessed from outside package.
I presume you're attempting to do this for testing purposes (stubbing?). In general (not gonna say best practice, since I'm not that entirely sure that it is best practice), it is advisable to have a separate method that accepts a specific value that you need. Referring to the official example (onMessageReceived) (removed some stuff):
#Override
public void onMessageReceived(RemoteMessage remoteMessage) {
Log.d(TAG, "From: " + remoteMessage.getFrom());
// Check if message contains a data payload.
if (remoteMessage.getData().size() > 0) {
Log.d(TAG, "Message data payload: " + remoteMessage.getData());
if (/* Check if data needs to be processed by long running job */ true) {
// For long-running tasks (10 seconds or more) use Firebase Job Dispatcher.
scheduleJob();
} else {
// Handle message within 10 seconds
handleNow();
}
}
// Check if message contains a notification payload.
if (remoteMessage.getNotification() != null) {
Log.d(TAG, "Message Notification Body: " + remoteMessage.getNotification().getBody());
}
// Also if you intend on generating your own notifications as a result of a received FCM
// message, here is where that should be initiated. See sendNotification method below.
}
/**
* Schedule a job using FirebaseJobDispatcher.
*/
private void scheduleJob() {
// [START dispatch_job]
FirebaseJobDispatcher dispatcher = new FirebaseJobDispatcher(new GooglePlayDriver(this));
Job myJob = dispatcher.newJobBuilder()
.setService(MyJobService.class)
.setTag("my-job-tag")
.build();
dispatcher.schedule(myJob);
// [END dispatch_job]
}
/**
* Handle time allotted to BroadcastReceivers.
*/
private void handleNow() {
Log.d(TAG, "Short lived task is done.");
}
/**
* Create and show a simple notification containing the received FCM message.
*
* #param messageBody FCM message body received.
*/
private void sendNotification(String messageBody) {
Intent intent = new Intent(this, MainActivity.class);
intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
PendingIntent pendingIntent = PendingIntent.getActivity(this, 0 /* Request code */, intent,
PendingIntent.FLAG_ONE_SHOT);
Uri defaultSoundUri= RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION);
NotificationCompat.Builder notificationBuilder = new NotificationCompat.Builder(this)
.setSmallIcon(R.drawable.ic_stat_ic_notification)
.setContentTitle("FCM Message")
.setContentText(messageBody)
.setAutoCancel(true)
.setSound(defaultSoundUri)
.setContentIntent(pendingIntent);
NotificationManager notificationManager =
(NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
notificationManager.notify(0 /* ID of notification */, notificationBuilder.build());
}
Focusing on the comment that mentions:
Also if you intend on generating your own notifications as a result of a received FCM message, here is where that should be initiated. See sendNotification method below.
This points out the sendNotification() method that accepts a String parameter. Depending on your case, instead of attempting to pass an initialized RemoteMessage (which sadly isn't possible, or at the very least is not advisable), you could simply pass an object that your method needs.
With that, you pretty much tested the method that handles the message without depending on an object that isn't a class you made in the first place.
PS: Some of my explanations can be confusing, but I hope this made sense.

Android Parse.com push notification not sent

Background
I have an Android app with a working receiver that can receive the push notification sent from iOS device and Parse website.
However, the following cases are not working:
send push notifications from Android to Android
send push notifications from Android to iOS
Since the Android app can receive push notifications without any problems, I guess there must be something with my logic/code of sending the push notifications
Problem Description
When sending push notifications using parsePush.sendInBackground(SendCallback) method, it returns no ParseExceptions. So it means no error.
But the Parse Dashboard does not show this push notifications and the target destination (either iOS or Android device in this case) does not get anything.
In the normal case, when a push notification is sent via Parse, it will show up as a push history in the Dashboard (the working case does that), but when I tried to send pushes from Android device, it just not show anything in the Dashboard and the pushes are never get delivered.
Code
The problematic Android code:
public void onShouldSendPushData(MessageClient messageClient, Message message, List<PushPair> pushPairs) {
//TODO setup offline push notification
Log.d(TAG, "Recipient not online. Should notify recipient using push");
if (pushPairs.size() > 0 && !chatRecipient.isEmpty()) {
PushPair pp = pushPairs.get(0);
String pushPayload = pp.getPushPayload();
ParsePush parsePush = new ParsePush();
ParseQuery query = ParseInstallation.getQuery();
ParseQuery userQuery = ParseUser.getQuery();
userQuery.whereEqualTo("username", chatRecipient);
query.whereMatchesQuery("user", userQuery);
parsePush.setQuery(query);
// JSON object for android push
String alertString = getResources().getString(R.string.push_notification_msg);
try {
JSONObject data = new JSONObject();
data.put("alert", String.format(alertString, chatRecipient));
data.put("badge", "Increment");
data.put("sound", "default");
// pass the sender name as "title"
data.put("title", ParseUser.getCurrentUser().getUsername());
data.put("uri", "");
data.put("SIN", pushPayload);
parsePush.setData(data);
parsePush.sendInBackground(new SendCallback() {
#Override
public void done(ParseException e) {
if (e == null) {
Log.i(TAG, String.format("Push notification to %s sent successfully", chatRecipient));
} else {
Log.e(TAG, String.format("Private chat push notification sending error: %s", e.getMessage()));
}
}
});
} catch (JSONException e) {
e.printStackTrace();
}
}
}
The working iOS code:
- (void)message:(id<SINMessage>)message shouldSendPushNotifications:(NSArray *)pushPairs {
// use parse to send notifications
// send notifications
NSLog(#"Recipient not online. Should notify recipient using push");
if (pushPairs.count > 0 && userSelected != nil) {
pushData = [[pushPairs objectAtIndex:0] pushData];
pushPayload = [[pushPairs objectAtIndex:0] pushPayload];
PFPush *push = [[PFPush alloc] init];
PFQuery *query = [PFInstallation query];
PFQuery *userQuery = [PFUser query];
[userQuery whereKey:#"username" equalTo:userSelected];
[query whereKey:#"user" matchesQuery:userQuery];
[push setQuery:query];
NSDictionary *data = [NSDictionary dictionaryWithObjectsAndKeys:
[NSString stringWithFormat:#"You have a new Message from %#", [PFUser currentUser].username], #"alert",
#"Increment", #"badge",
#"default", #"sound",
pushPayload, #"SIN",
nil];
[push setData:data];
[push sendPushInBackgroundWithBlock:^(BOOL succeeded, NSError *error) {
if (succeeded) {
NSLog(#"Push notification to %# sent successfully.", userSelected);
} else {
NSLog(#"push notifications sending error: %#", error);
}
}];
} else {
NSLog(#"Error: No push pairs.");
}
Note
I can confirm that the code above is getting called each time I want to send push notifications, and no exceptions are returned. I can also confirm that the data packaged inside the push is not null.
I'm not posting the receiver's code as that part of code is working and should do nothing with this issue.
The iOS code and Android code basically are the same, why the sending pushes function in Android not working?
UPDATE
I upgraded Parse SDK to 1.8.2, with its Logging options set to VERBOSE and still can't find any clue why the Push notifications are not sent.
I even made a simple project out of the Parse example project with only Login and send message functions and its sending message function is still not working. So frustrating.
I have found the reason.
It is the "uri" field inside JSON.
As long as this field is included (with or without the content), notifications seemed being ignored by Parse, although you'll get a non-error callback.
If you remove "uri" field inside your JSON, notifications will become normal.
I've reported this bug to Parse and they've started to solve it.
Update
According to the reply from Parse.com, this is an intended feature, so the notifications with "uri" field will be discarded on the server side, thus it will not be sent.
related link:
https://developers.facebook.com/bugs/338005256408244

Categories

Resources