Firebase offers two ways to seding a push notifications, using it's firebase console and using a server like in GCM was did before. Now we are translating our servers from GCM to Firebase, and we need to receive and show FCM notifications in the app.
I have the implementation of the official firebase website done, with the sample codes done, but I'm stuck on this part. When our server sends the push notification to Firebase, and firebase send's to my app, I'm receiving the notification in onMessageReceived method with a RemoteMessage parameter. I know that the message is inside RemoteMessage parameter, but I can't find any guide or sample code in the Firebase official documentation about how to deal with this to show the notification text on the android device notification bar.
As you can see on the official guides, it is not explained how to extract the message without problems from the RemoteMessage parameter. I know that you can search inside and find the String but I want to find a official guide about how to correctly and safely deal with this.
In the official documentation you have only this:
#Override
public void onMessageReceived(RemoteMessage remoteMessage) {
// TODO(developer): Handle FCM messages here.
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());
// Handle message within 10 seconds
}
// 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.
}
And this (which is not being called on the guide):
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_main)
.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());
}
I have done something like this I am using addNotifcation() in place of sendNotification()
public class MyFirebaseMessagingService extends FirebaseMessagingService {
private static final String TAG = "FCM Service";
#Override
public void onMessageReceived(RemoteMessage remoteMessage) {
Log.d(TAG, "From: " + remoteMessage.getFrom());
Log.d(TAG, "Notification Message Body: " + remoteMessage.getData().get("body"));
addNotification(remoteMessage.getData().get("body"), remoteMessage.getData().get("Nick"));
}
private void addNotification(String message, String title) {
NotificationCompat.Builder builder =
(NotificationCompat.Builder) new NotificationCompat.Builder(this);
builder.setSmallIcon(R.mipmap.ic_launcher1)
.setContentTitle(title)
.setContentText(message);
Intent notificationIntent = new Intent(this, app.class);
PendingIntent contentIntent = PendingIntent.getActivity(this, 0, notificationIntent,
PendingIntent.FLAG_UPDATE_CURRENT);
builder.setContentIntent(contentIntent);
// Add as notification
NotificationManager manager = (NotificationManager) this.getSystemService(Context.NOTIFICATION_SERVICE);
manager.notify(0, builder.build());
}
You will recieve a json onMessageRecieve from server then you need to parse that json and get values out of it.Once you have parsed value you can send it with sendNotification() Method and show what you require
Check below method, its working fine, I am getting json data from server in notification.
public class MyFirebaseMessagingService extends FirebaseMessagingService {
private static final String TAG = "MyFirebaseMsgService";
#Override
public void onMessageReceived(RemoteMessage remoteMessage) {
AppLog.Log(TAG, "From: " + remoteMessage.getFrom());
JSONObject json = null;
if (remoteMessage.getData().size() > 0) {
Log.v(TAG, "Message data " + remoteMessage.getData());
json = new JSONObject(remoteMessage.getData());
AppLog.Log(TAG, "Json object " + json);
}
if (json != null) {
try {
int icon = R.mipmap.ic_launcher;
int mNotificationId = 001;
// MainDrawerActivity is the class which open on the click of notification in status bar
Intent intent = new Intent(this, MainDrawerActivity.class);
intent.addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP);
//FLAG_UPDATE_CURRENT is important
PendingIntent pendingIntent = PendingIntent.getActivity(this, (int) System.currentTimeMillis(), intent, PendingIntent.FLAG_UPDATE_CURRENT);
NotificationCompat.Builder mBuilder = new NotificationCompat.Builder(
this);
Notification notification = mBuilder.setSmallIcon(icon).setTicker("your title").setWhen(0)
.setAutoCancel(true)
.setContentTitle("your title")
.setStyle(new NotificationCompat.BigTextStyle().bigText("message"))
.setContentIntent(pendingIntent)
.setContentText("message").build();
NotificationManager notificationManager = (NotificationManager) this.getSystemService(Context.NOTIFICATION_SERVICE);
notificationManager.notify(mNotificationId, notification);
} catch (Exception e) {
e.printStackTrace();
}
}
}
}
Related
I've been developing android apps for a while now and all of them have FCM integrated in them and functioning properly.
I have this app that the onMessageReceived isn't fired unless the app is opened, if the app is closed and I receive a notification it opens from splash and follows the normal flow (it doesn't go to the Notifications activity).
N.B: all the testing I've done was from the Firebase Console
I really don't know why, any help would be appreciated.
Here's my code:
public class MyFirebaseMessagingService extends FirebaseMessagingService {
private static final String TAG = "MyFirebaseMsgService";
#Override
public void onMessageReceived(RemoteMessage remoteMessage) {
Log.wtf("RECEIVED","NOTIFICATION");
// TODO(developer): Handle FCM messages here.
Log.wtf(TAG, "From: " + remoteMessage.getFrom());
// Check if message contains a data payload.
if (remoteMessage.getData().size() > 0) {
Log.wtf(TAG, "Message data payload: " + remoteMessage.getData());
}
// Check if message contains a notification payload.
if (remoteMessage.getNotification() != null) {
Log.wtf(TAG, "Message Notification Body: " + remoteMessage.getNotification().getBody());
}
sendNotification("Notification");
}
private void sendNotification(String messageBody) {
Intent intent = new Intent(this, HomeActivity.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.mipmap.icon)
.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());
}
}
Using Firebase, you can send two type of notifications message basically.
1. Notification messages : sometimes thought of as "display messages."
2. Data/Payload messages : which are handled by the client app.
both above Notification has different behaviour, depending upon if your app is in foreground or background.
1.Notification msg + Background : delivered to the notification tray
2.Notification msg + Foreground : onMessageReceived() on Android
3.Data msg + Background : apps receive the notification payload in the notification tray, and only handle the data payload when the user taps on the notification.
4.Data msg + Foreground : your app receives a message object with both payloads available.
For more clarification check this.
For sending Data/payload message using FCM console use Advance option and insert key and value.
This question already has answers here:
Firebase onMessageReceived not called when app in background
(30 answers)
Closed 6 years ago.
In Firebase onMessageReceived(RemoteMessage remoteMessage), this method will be called when your app is in Foreground. So, on clicking the notification you can open a different Activity, say NotiicationActivity.
But what if your app is in background, then this method will not be called, and on clicking the notification only a Launcher Activity will be opened.
So how to open the NotificationActivity on clicking the notification even if our app is in background.
My Code is this :
public class MyFirebaseMessagingService extends FirebaseMessagingService {
private static final String TAG = "MyFirebaseMsgService";
#Override
public void onMessageReceived(RemoteMessage remoteMessage) {
Log.d(TAG, "From: " + remoteMessage.getFrom());
if (remoteMessage.getData().size() > 0) {
Log.d(TAG, "Message data payload: " + remoteMessage.getData());
}
if (remoteMessage.getNotification() != null) {
Log.d(TAG, "Message Notification Body: " + remoteMessage.getNotification().getBody());
}
sendNotification(remoteMessage.getNotification().getBody());
}
private void sendNotification(String messageBody) {
Intent intent = new Intent(this, NewActivity.class);
intent.putExtra("key", messageBody);
intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
PendingIntent pendingIntent = PendingIntent.getActivity(this, 0 /* Request code */, intent,
PendingIntent.FLAG_ONE_SHOT);
Bitmap icon2 = BitmapFactory.decodeResource(getResources(),
R.mipmap.ic_launcher);
Uri defaultSoundUri = RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION);
NotificationCompat.Builder notificationBuilder = new NotificationCompat.Builder(this)
.setSmallIcon(R.mipmap.ic_launcher)
.setContentTitle("FCM Sample")
.setContentText(messageBody)
.setAutoCancel(true)
.setLargeIcon(icon2)
.setSound(defaultSoundUri)
.setContentIntent(pendingIntent);
NotificationManager notificationManager =
(NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
notificationManager.notify(new Random().nextInt() /* ID of notification */, notificationBuilder.build());
}
}
onMessageReceived is only triggered when the application is in foreground.
If the app is backgrounded, you may still be able to receive the notification but onMessageReceived will not be triggered.
So my suggestion,
on the receiving activity, you can still get the data from the notification by using:
getIntent().getExtras();
This should work accordingly. Hope this helps :)
try and follow below link :
Firebase Cloud Messaging for Android
In your sendNotification() method :
private void showNotification(String message){
Intent intent=new Intent(this, NotificationActivity.class);
intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
intent.putExtra("key", messageBody);
PendingIntent pendingIntent=PendingIntent.getActivity(this,0,intent,PendingIntent.FLAG_UPDATE_CURRENT);
NotificationCompat.Builder builder=new NotificationCompat.Builder(this)
.setAutoCancel(true)
.setContentTitle("FCM Sample")
.setContentText(message)
.setLargeIcon(icon2)
.setContentIntent(pendingIntent);
NotificationManager manager=(NotificationManager) getSystemService(NOTIFICATION_SERVICE);
manager.notify(0,builder.build());
}
This question already has answers here:
FCM Schedule delivery date or time of push notification
(2 answers)
Closed 6 years ago.
I am trying to schedule particular time and want to send notification using Firebase. I am working on the project where I have to send the notification before the match start. Currently my notification is working on real time but I can't found any way to schedule it for the specific time.
For the real time I am using this particular code.
//Class extending service as it is a service that will run in background
public class NotificationFirebaseListener extends FirebaseMessagingService {
private static final String TAG = "MyFirebaseMsgService";
String test;
#Override
public void onMessageReceived(RemoteMessage remoteMessage) {
Log.e(TAG, "From: " + remoteMessage.getFrom());
Log.e(TAG, "Notification Message Body: " + remoteMessage.getNotification().getBody() + "=====>");
if (remoteMessage.getData().size() > 0) {
Log.e(TAG, "Message data payload: " + remoteMessage.getData());
test = String.valueOf(remoteMessage.getData());
}
sendNotification(test);
}
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, intent,
PendingIntent.FLAG_ONE_SHOT);
Uri defaultSoundUri = RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION);
NotificationCompat.Builder notificationBuilder = new NotificationCompat.Builder(this)
.setSmallIcon(R.mipmap.ic_launcher)
.setContentTitle("Bus Tracking")
.setContentText(messageBody)
.setAutoCancel(true)
.setSound(defaultSoundUri)
.setContentIntent(pendingIntent);
NotificationManager notificationManager =
(NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
notificationManager.notify(0, notificationBuilder.build());
}
}
The best way to achieve this is use the Firebase Notification composer to schedule your notifications for your app: https://firebase.google.com/docs/notifications/.
If you want another way to achieve these via code, I suggest you to schedule your notification using a ScheduledThreadPool. You can read more about this in the oracle documentation: https://docs.oracle.com/javase/7/docs/api/java/util/concurrent/ScheduledThreadPoolExecutor.html.
I have implemented push by firebase.
I'm sending notifications but I am getting status of "Failed". When I send notification to all devices it is marking as completed but I am still not getting messages in device.
Even when I send messages to single devices it will also show failed and will not receive notification on device.
The code is
private static final String TAG = "StartingAndroid";
#Override
public void onMessageReceived(RemoteMessage remoteMessage) {
//It is optional
Log.e(TAG, "From: " + remoteMessage.getFrom());
Log.e(TAG, "Notification Message Body: " + remoteMessage.getNotification().getBody());
//Calling method to generate notification
sendNotification(remoteMessage.getNotification().getTitle(),remoteMessage.getNotification().getBody());
}
//This method is only generating push notification
private void sendNotification(String title, String messageBody) {
Intent intent = new Intent(this, MainActivity.class);
intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
PendingIntent pendingIntent = PendingIntent.getActivity(this, 0, intent,
PendingIntent.FLAG_ONE_SHOT);
Uri defaultSoundUri= RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION);
NotificationCompat.Builder notificationBuilder = new NotificationCompat.Builder(this)
.setSmallIcon(R.mipmap.ic_launcher)
.setContentTitle(title)
.setContentText(messageBody)
.setAutoCancel(true)
.setSound(defaultSoundUri)
.setContentIntent(pendingIntent);
NotificationManager notificationManager =
(NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
notificationManager.notify(0, notificationBuilder.build());
}
Your sender ID mismatched or you have entered incorrect project ID in your Application.
Looking at logs, I think you are sending to specific devices via registration id but we see an error with mismatched sender id.Please check that these registration ids are valid and apply to the correct app.
I am having problem with FireBase push notifications. When my app is in the background, notifications are coming, but when my app is in the foreground i don't receive notifications, but in console that notification is displayed, that means that notification is here but it doesn't show in notification bar . Could you help me?
#Override
public void onMessageReceived(RemoteMessage remoteMessage) {
Log.d("OnMessage", "Received");
super.onMessageReceived(remoteMessage);
Log.d(TAG, "From " + remoteMessage.getFrom());
Log.d(TAG, "Body " + remoteMessage.getNotification().getBody());
String aa=remoteMessage.toString();
Intent intent=new Intent(MyFirebaseMessagingService.this, MainActivity.class);
intent.putExtra("msg", aa);
sendNotification(remoteMessage);
NotificationCompat.Builder mBuilder =
new NotificationCompat.Builder(this)
.setContentText(remoteMessage.getNotification().getBody());
// remoteMessage.getNotification().getBody();
}
private void sendNotification(RemoteMessage remoteMessage) {
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)
.setContentText(remoteMessage.getNotification().getBody())
.setAutoCancel(true)
.setSound(defaultSoundUri)
.setContentIntent(pendingIntent);
NotificationManager notificationManager =
(NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
notificationManager.notify(0 /* ID of notification */, notificationBuilder.build());
}
EDIT:
I just noticed that onMessageReceived() of FirebaseMessagingService is not invoked(as of now) when you send notifications from console and your app is in foreground. One solution is you can use Firebase APIs to send push notifications and it will invoke onMessageReceived() regardless of app being in foreground or background.
If you use "notification" body to send push notification i.e.
notification: {
title: "notification title",
icon: "ic_launcher",
color: "#4E2AA5",
body: "notification body"
}
To retrieve this in onMessageReceived(), use something like this:
String color = remoteMessage.getNotification().getColor();
String body = remoteMessage.getNotification().getBody();
String title = remoteMessage.getNotification().getTitle();
String icon = remoteMessage.getNotification().getIcon();
If your app is in background, Firebase will display a notification corresponding to the data you set in push and will also invoke onMessageReceived(). Thus you will see 2 notifications if you have also written code to show custom notification in onMessageReceived().
To work around this, you can use some "data" key like this:
data: {
title: "notification title",
body: "notification body"
}
and to retrieve it in onMessageReceived(), use something like this:
Map<String, String> map = remoteMessage.getData();
for (Map.Entry<String, String> entry : map.entrySet()) {
Log.d(TAG, entry.getKey() + "/" + entry.getValue());
}
You can then build your own custom notification and display it from onMessageReceived() only that notification will show up.
P.S. Please vote up if it helps. I am new to stackoverflow.
Like you said you are receiving the message since you are seeing the log messages in the console so you have handled the FCM part properly and the issue is likely with your creation of the notification.
If you look at your notification creation code you are missing a couple of the required elements to create a notification on Android. From the docs:
A Notification object must contain the following:
A small icon, set by setSmallIcon()
A title, set by setContentTitle()
Detail text, set by setContentText()
So I think if you add those items to your notification creation you should see the notification in the notification area.
Intent intent = new Intent(this, "your class");
intent.addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP);
PendingIntent pendingIntent = PendingIntent.getActivity(this, 0 /* Request code */, intent,
PendingIntent.FLAG_ONE_SHOT);
NotificationManager notificationManager = (NotificationManager) getApplicationContext().getSystemService(Context.NOTIFICATION_SERVICE);
NotificationCompat.Builder builder = null;
if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.O) {
int importance = NotificationManager.IMPORTANCE_DEFAULT;
NotificationChannel notificationChannel = new NotificationChannel("ID", "Name", importance);
notificationManager.createNotificationChannel(notificationChannel);
builder = new NotificationCompat.Builder(getApplicationContext(), notificationChannel.getId());
} else {
builder = new NotificationCompat.Builder(getApplicationContext());
}
builder = builder
.setSmallIcon(R.mipmap.ic_app_icon)
.setColor(ContextCompat.getColor(getApplicationContext(), R.color.picker_button_background_innactive))
.setContentTitle((messageBody))
.setTicker(title)
.setContentText(message_body)
.setDefaults(Notification.DEFAULT_ALL)
.setContentIntent(pendingIntent)
.setAutoCancel(true);
notificationManager.notify(1, builder.build());