I am struggling with FCM notifications on Android. The issue is only when the app is closed and not running. I am trying to achieve no click activity I don't want the app to open and I do not want the message to disappear. It works perfectly when the app is open and running. When the app is not open I still get the notification but it is not in multi-line so I can only see the beginning of the notification. Then clicking on the notification makes it disappear. I have spent hours trying to find a solution that works. Here is the code i have so far:
private void sendNotification(String messageBody) {
//Intent intent = new Intent(this, MainActivity.class);
// intent.setFlags(Intent.FLAG_ACTIVITY_NO_USER_ACTION);
//PendingIntent pendingIntent = PendingIntent.getActivity(this, 0, intent,
// PendingIntent.FLAG_UPDATE_CURRENT);
Uri defaultSoundUri= RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION);
NotificationCompat.Builder notificationBuilder = new NotificationCompat.Builder(this)
.setSmallIcon(R.mipmap.ic_launcher)
.setContentTitle("My Car Wash App")
.setAutoCancel(true)
.setSound(defaultSoundUri)
.setContentText(messageBody)
.setDefaults(NotificationCompat.DEFAULT_ALL)
.setStyle(new NotificationCompat.BigTextStyle().bigText(messageBody))
.setPriority(NotificationCompat.PRIORITY_MAX);
NotificationManager notificationManager =
(NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
notificationManager.notify(0, notificationBuilder.build());
}
Any help or suggestions would be greatly appreciated.
EDIT *******
The problem is I asked the question poorly after more research I now realize the code above is only being called when my app is open.
#Override
public void onMessageReceived(RemoteMessage remoteMessage) {
//Displaying data in log
//It is optional
Log.i("myStuff", "From: " + remoteMessage.getFrom());
Log.i("myStuff", "Notification Message Body: " + remoteMessage.getNotification().getBody());
//Calling method to generate notification
sendNotification(remoteMessage.getNotification().getBody());
}
onMessageReceived is not called when the app is not in the foreground that is why the notifications are not showing multi-line unless the app is running. There is a lot of information posted on this subject but I still can not seem to figure it out.
Here is my c# server side code
*
var data = new
{
to = deviceId,
notification = new
{
body = msg,
title = "My Car Wash",
icon = "myicon"
},
priority = 10
};
Notifications work perfect on iOS and perfect on Android when the app is running. I just can not get the message to show in multi-line correctly and I am not sure what to do.
*
The notification is getting disappeared when you click on it because you did not add any action when onClick is performed.
To give onClick functionality on notification, you have to use PendingIntent with the target activity. You can also add additional data into it if needed.
Before initializing notificationManager, add this code:
Intent openIntent = new Intent(mContext, TargetActivity.class);
// Falg to clear the stack.
openIntent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_ACTIVITY_SINGLE_TOP);
PendingIntent pendingIntent = PendingIntent.getActivity(mContext, 0,
openIntent, 0);
notificationBuilder.setContentIntent(pendingIntent);
FCM displays my notification the way it wants to when the app is closed. That's ok with me. I just want to make sure the entire notification gets read and not lost. Here is my solution...
When an app user clicks on the notification it opens the app and displays the notification in an alert Dialog.
c# server-side code to send the message
var msg2send = new
{
to = deviceId,
priority = 10,
notification = new
{
body = msg,
title = "Red Hill Car Wash",
icon = "myicon"
},
data = new
{
notice = msg
}
};
And in the onCreate of MainActivity
String notice = "";
try {
notice = getIntent().getStringExtra("notice");
if (notice != null)
{
Log.i("myStuff", notice);
///// DISPLAY NOTIFICATION IN AN ALERT DIAGLOG all good!
}
}
catch (Exception ex) {
Log.i("myStuff", ex.getMessage());
}
FCM passes the message to my MainActivity, if a message exists then I grab it and can display it how ever I want. Thank for the comments and input to help solve this issue.
One way is to use data instead of notification to get onMessageReceived() callback both in app foreground or background. The json part is:
{
"data": {
"title": "notification_title",
"body": "notification_body"
},
"to" : "jh578_gsh....jhHGFJ76FH"
}
For detail, follow this link: https://stackoverflow.com/a/37845174/5829624
Edit:
Method 2:
Use a click_action payload in your notification payload. In json:
{
"notification": {
"click_action": "OPEN_ACTIVITY_1",
},
}
And add this intent filter in the Activity (which you want to load when you tap on the notification) in your Manifest:
<intent-filter>
<action android:name="OPEN_ACTIVITY_1" />
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
Hope this one will solve your problem.
When application in background "OnMessageReceived" overridden method wont get called in general scenario.
If you want to make "OnMessageReceived" method to call all the time. Ask your web service team to send only "DATA" payload. Dont use "Notify" or "Notification" payload.
If "DATA" payload is send properly from backend then Android application will work on "OnMessageReceived" with a List of Data from RemoteMessage.getDATA();
I struggled the same issue for nearly 2 days and finally got the above solution.
Related
Here is my code, When my app is running in foreground it opens targeted activity but when app is closed or in background, it doesn't opens targeted activity, please help me to solve this problem
I want that by clicking on notification will open targeted activity even app is running / closed.
public void onMessageReceived(RemoteMessage remoteMessage) {
session = new Session(this);
// if (session.getBscloggedin() || session.getAdploggedin()) {
// Log.d(TAG, "FROM:" + remoteMessage.getFrom());
//Check if the message contains data
if (remoteMessage.getData().size() > 0) {
Log.d(TAG, "Message data: " + remoteMessage.getData());
}
//Check if the message contains notification
if (remoteMessage.getNotification() != null) {
Log.d(TAG, "Mesage body:" + remoteMessage.getNotification().getBody());
sendNotification(remoteMessage.getNotification().getBody());
}
}
/**
* Dispay the notification
* #param body
*/
private void sendNotification(String body) {
//for CS101 announcement notification
if (body.contains("CS101")) {
Intent intent = new Intent(this, CS101noti.class);
intent.putExtra("body", body);
intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP |
Intent.FLAG_ACTIVITY_SINGLE_TOP);
PendingIntent pendingIntent = PendingIntent.getActivity(this, 0/*Request code*/, intent, 0);
//Set sound of notifica tion
Uri notificationSound = RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION);
NotificationCompat.Builder notifiBuilder = new NotificationCompat.Builder(this)
.setSmallIcon(R.mipmap.ic_launcher)
.setContentTitle("mine")
.setContentText(body)
.setAutoCancel(true)
.setSound(notificationSound)
.setContentIntent(pendingIntent);
NotificationManager notificationManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
notificationManager.notify(0 /*ID of notification*/, notifiBuilder.build());
}
Request code should be unique.
Generally people share with us example like giving request code 0(zero). I am the one of copy/paste developer sometimes. But recently I faced with error using this line.
PendingIntent.getActivity(myContext, 0, myIntent, 0);
Whenever app receives notification, intent activity receives old data because of requestCode. Here is the documentation about that method.
Returns an existing or new PendingIntent matching the given
parameters.
So second parameter(requestCode) should be unique to intent. If you use same request code for every notification, activity will be receive old data. So your requestCode should be unique.
There is also another solution.Use PendingIntent.FLAG_UPDATE_CURRENT as flag. The doc says that;
If the described PendingIntent already exists, then keep it but
replace its extra data with what is in this new Intent.
onMessageReceived callback is not called when you receive notification messages in background. If you receive this type of message in background, you can only handle that in a launcher activity.
The solution would be to either change the backend so that it sends only data messages and you handle them internally, or write some routing code inside your launcher activity.
use "click_action" attribute from your backend from which you are sending push notifications. in that attribute value, you have to pass the fully qualified class path of activity, which should be opened when you click on that notification.for more reference refer handling firebase push
Intent intent = new Intent(this, CS101noti.class);
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
....
I am only receiving push notification when app is in background, I couldn't find what exactly triggered when my app receive push . I just want to change the notification body , as an example if the notification message is "hi" I want to show user "hi user".
public class MyFcmListenerService extends FirebaseMessagingService {
#Override
public void onMessageReceived(RemoteMessage message) {
//nothing triggered here when app is in background
}
}
$fields = array(
'registration_ids' => $reg_id ,
'priority' => "high",
'data' => array(******));
curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($fields));
I have faced the same problem. Removed notification key values from my PHP firebase Service. My issues got resolved. I am just using registration_ids,
priority, data
You can, you only need to know how firebase push notifications work in android.
you need to override
handleIntent function.
This function handle Firebase notifications in background. So inside it you will make your push notification taking all the data sent in push message. Don't forget extract information from message. You can use default spaces like title or body but also you can send some custom data.
Next I will attach a example code how it works.
Note: if you haven't this method then you need to upgrade firebase version up than 10.0.1
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.
Log.d(TAG, "From: " + remoteMessage.getFrom());
Log.d(TAG, "Notification Message Body: " + remoteMessage.getNotification().getBody());
}
#Override
public void handleIntent(Intent intent) {
//super.handleIntent(intent);
Log.d(TAG,"Handling Intent");
Bundle mBundle = intent.getExtras();
String img = mBundle.getString("imgURL");
String title = mBundle.getString("gcm.notification.title");
String body = mBundle.getString("gcm.notification.body");
mBundle.putInt("promoId",Integer.valueOf(mBundle.getString("promoId")));
Integer id = mBundle.getInt("promoId");
sendNotification(mBundle);
}
private void sendNotification(Bundle mBundle) {
// Create an explicit content Intent that starts the main Activity.
Intent notificationIntent = new Intent(getApplicationContext(), MainActivity.class);
notificationIntent.putExtras(mBundle);
// Construct a task stack.
TaskStackBuilder stackBuilder = TaskStackBuilder.create(this);
// Add the main Activity to the task stack as the parent.
stackBuilder.addParentStack(MainActivity.class);
// Push the content Intent onto the stack.
stackBuilder.addNextIntent(notificationIntent);
// Get a PendingIntent containing the entire back stack.
PendingIntent notificationPendingIntent =
stackBuilder.getPendingIntent(0, PendingIntent.FLAG_UPDATE_CURRENT);
// Get a notification builder that's compatible with platform versions >= 4
NotificationCompat.Builder builder = new NotificationCompat.Builder(this);
String title = mBundle.getString("gcm.notification.title");
String body = mBundle.getString("gcm.notification.body");
// Define the notification settings.
builder.setSmallIcon(R.mipmap.ic_launcher)
// In a real app, you may want to use a library like Volley
// to decode the Bitmap.
.setLargeIcon(BitmapFactory.decodeResource(getResources(),
R.mipmap.ic_launcher))
.setColor(Color.RED)
.setContentTitle(title)
.setContentText(body)
.setContentIntent(notificationPendingIntent);
// Dismiss notification once the user touches it.
builder.setAutoCancel(true);
// Get an instance of the Notification manager
NotificationManager mNotificationManager =
(NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
// Issue the notification
mNotificationManager.notify(0, builder.build());
}
}
if you have any question ask and I will edit mi answer.
I am sending push notification from firebase to my Android Application. but when my app is in background firebase onMessageReceived method is not called instead firebase send notification to system for showing notification in system tray. notification appears in system tray but no sound for notification even i have allowed notification sound for my app in system settings.
this my code for notification
thank you
private void sendNotification(String msg, String title) {
NotificationManager mNotificationManager = (NotificationManager)
this.getSystemService(Context.NOTIFICATION_SERVICE);
PendingIntent contentIntent = PendingIntent.getActivity(this, 0,
new Intent(this, MainActivity.class), 0);
Intent i = new Intent(this,MainActivity.class);
i.putExtra("","");
NotificationCompat.Builder mBuilder =
new NotificationCompat.Builder(this)
.setSmallIcon(R.mipmap.ic_launcher)
.setContentTitle(title)
.setStyle(new NotificationCompat.BigTextStyle().bigText(msg))
.setContentText(msg);
//Vibration
mBuilder.setVibrate(new long[] { 200, 400, 600, 800, 1000 });
//LED
mBuilder.setLights(Color.MAGENTA, 1000, 1000);
//Ton
mBuilder.setSound(Uri.parse("android.resource://"
+ getApplicationContext().getPackageName() + "/" + R.raw.circles_notif));
mBuilder.setContentIntent(contentIntent);
mNotificationManager.notify(0, mBuilder.build());
}
Go to Notifications> New Message> Advanced Options from your firebase console and send notification as Custom data. Use 'title' and 'body' as Key and put their values as you want to show them in notification. This should call onMessageReceived() when your app is in background or killed.
If you are sending notification from your own server, here is a sample json part:
{
"data": {
"title": "notification_title",
"body": "notification_body"
},
"to" : "jh578_gsh....jhHGFJ76FH"
}
It's written in the override sample of onMessageReceived(), the second comment line says:
#Override
public void onMessageReceived(RemoteMessage remoteMessage) {
...
Not getting messages here? See why this may be: ...goo.gl/39bRNJ
...
}
see comment-link
The solution, like the answers for the related question: How to handle notification when app in background in Firebase, can be found in the documentation in Messages with both notification and data payloads section which says:
App behavior when receiving messages that include both notification and data payloads depends on whether the app is in the background or the foreground—essentially, whether or not it is active at the time of receipt.
When in the background, apps receive the notification payload in the notification tray, and only handle the data payload when the user taps on the notification.
When in the foreground, your app receives a message object with both payloads available.
This seem to work for me YMMV
{
"notification": {
"title": "notification_title",
"body": "notification_body",
"sound": "default"
},
"to" : "device....id"
}
While this will not wake up your app if background while the accepted answer will.
I am implementing GCM service in my android app and i am getting notification also.But we get problem when my app is closed or in background.
When app is in foreground then everything is working fine, I am getting notification with all text and icon but when my app is in background, we get notification text and title but icon is not visible. I searched about this and reached the conclusion that notification is handled by device notification tray when your app is in background.
Here is my code to receive notification:
public class GCMPushReceiverService extends GcmListenerService {
//This method will be called on every new message received
#Override
public void onMessageReceived(String from, Bundle data) {
//Getting the message from the bundle
String message = data.getString("message");
Log.d("data",data.toString());
//Displaying a notiffication with the message
String body = null;
String title = null;
try{
String data1 = data.toString();
String json = (data1.split("notification=Bundle\\[")[1]).split("\\]")[0];
body = (json.split("body\\=")[1]).split("\\,")[0];
// title = (((json.split("body\\=")[1]).split("\\,")[1]).split("title\\=")[1]).split("\\,")[0];
title = (((json.split("body\\=")[1]).split("vibrate")[0]).split("title=")[1]).split(",")[0];
Log.d("json",json);
JSONObject notificationJSON = new JSONObject(json);
//String notificationJSONString = data.getString("notification");
//then you can parse the notificationJSONString into a JSON object
// JSONObject notificationJSON = new JSONObject(notificationJSONString );
// body = notificationJSON.getString("body");
//title = notificationJSON.getString("title");
Log.d("body",body);
Log.d("title",title);
}catch (Exception e){
e.printStackTrace();
}
// sendNotification(message);
sendNotification(body, title);
}
//This method is generating a notification and displaying the notification
private void sendNotification(String message,String titles) {
Intent intent = new Intent(this, NavigationDrawerActivity.class);
intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
intent.putExtra("firsttab","notify");
int requestCode = 0;
int number = 0;
PendingIntent pendingIntent = PendingIntent.getActivity(this, requestCode, intent, PendingIntent.FLAG_ONE_SHOT);
Uri sound = RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION);
NotificationCompat.InboxStyle inboxStyle = new NotificationCompat.InboxStyle();
NotificationCompat.Builder noBuilder = new NotificationCompat.Builder(this)
// .setSmallIcon(R.mipmap.philips_launcher)
.setSmallIcon(getNotificationIcon())
.setContentTitle(titles)
.setContentText(message)
.setAutoCancel(true)
.setSound(sound)
.setNumber(++number)
.setColor(Color.parseColor("#0089C4"))
// .setStyle(inboxStyle)
.setStyle(new NotificationCompat.BigTextStyle().bigText(message))
.setStyle(new NotificationCompat.BigTextStyle().bigText(titles))
.setContentIntent(pendingIntent);
/* if (android.os.Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
builder.setSmallIcon(R.drawable.icon_transperent);
} else {
builder.setSmallIcon(R.drawable.icon);
}*/
NotificationManager notificationManager = (NotificationManager)getSystemService(Context.NOTIFICATION_SERVICE);
notificationManager.notify(0, noBuilder.build()); //0 = ID of notification
}
private int getNotificationIcon() {
boolean useWhiteIcon = (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.LOLLIPOP);
return useWhiteIcon ? R.drawable.notification_icon : R.drawable.not_icon;
}
}
My question is how to handled notification when my app is in background? And how to show notification icon when app is in background? When I clicked on notification it open launcherActivity but I want to open some otherActivity.
Based from this thread, when app is in the background, it needs server side to make a action. The data part will automatically saved in a intent and send to the activity contains that action in the content filter. Stated in this related SO question that notification messages automatically generate notifications based on the properties passed in the "notification" object of your downstream message request, however onMessageReceived is not called in this case. Check this tutorial. When in the background, apps receive the notification payload in the notification tray, and only handle the data payload when the user taps on the notification.
You can also set the priority to high when sending the message. It allows the GCM service to wake a sleeping device when possible and open a network connection to your app server.
You can check on these related links:
Push notification when app is in background
GcmListenerService is not called while application stoped. Android GCM
Android - Sending Push Notifications via GCM with app in foreground/background
Hope this helps!
It looks like you are sending a notification message, notification messages are delivered to onMessageReceived callback when the app is in the foreground like you are seeing. However when the app is in the foreground notification messages are NOT passed to onMessageReceived, the notification payload of the message is used to automatically display a notification. If there is an accompanying data payload that payload will be available in the extras of the launched intent when the user taps the notification.
If you want complete control of how messages are handled then you should use data messages, which are always delivered to the onMessageReceived callback.
See more on the different ways the two types of FCM messages are handled here.
Note:
- that if you are using the Firebase console to send the messages, it only supports notification messages at this time. Even if you add custom data, it will still be treated as a notification message on the client side.
- If you are using the REST API to send the notification message you can specify the click_action field to determine which Activity will be launched when the user clicks on the notification.
If you are using FCM, Add this in your app Manifest:
<!-- Set custom default icon. This is used when no icon is set for incoming notification messages. -->
<meta-data
android:name="com.google.firebase.messaging.default_notification_icon"
android:resource="#drawable/ic_stat_ic_notification" />
<!-- Set color used with incoming notification messages. This is used when no color is set for the incoming
notification message. -->
<meta-data
android:name="com.google.firebase.messaging.default_notification_color"
android:resource="#color/colorAccent" />
Only then the custom color & icon will be shown in the notification when the app is in background.
I'm trying to send notifications with FCM, it works as expected but i'm facing two different behaviours that I want to deal with because I'm using bigtextstyle and an action:
First case: App in foreground,
onReceiveMessage works as expected and notification is shown correctly
Second Case: App killed or in background,
the documentation says that messages are not handled in the onReceiveMessage event, and the layout of the notification is not the bigtextstyle one:
I tried to find a way for showing the desired layout, but nothing is working, they said that data payload is delivered in the extras of the intent of the launcher Activity!
So, what I want, is to show the same notification layout in the two cases, because some time I use the notification to trigger a call or to open a link in a browser not to open the app itself.
I sent my messages from Firebase Console as shown :
and here's the function that notify :
private void notifyMe(RemoteMessage rm){
String title = "";
String body = "";
String phone = "";
String link = "";
long time = System.currentTimeMillis();
Intent iCall;
PendingIntent pintCall = null;
Intent notificationIntent = null;
NotificationManager notificationManager;
notificationManager = (NotificationManager)FirebaseMessagingService.this.getSystemService(Context.NOTIFICATION_SERVICE);
if (rm.getNotification() != null) {
title = rm.getNotification().getTitle();
body = rm.getNotification().getBody();
}
if (rm.getData().size() > 0) {
phone = rm.getData().get("phone");
link = rm.getData().get("link");
if(link.contains("http://")){
notificationIntent = new Intent(Intent.ACTION_VIEW, Uri.parse(link));
}else{
notificationIntent = new Intent(FirebaseMessagingService.this, MainActivity.class);
}
if(phone.equalsIgnoreCase("")){
iCall = new Intent(Intent.ACTION_DIAL, Uri.fromParts("tel", phone, null));
pintCall = PendingIntent.getActivity(FirebaseMessagingService.this, 0, iCall, PendingIntent.FLAG_UPDATE_CURRENT);
}
}
notificationIntent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_ACTIVITY_NEW_TASK );
PendingIntent pint = PendingIntent.getActivity(FirebaseMessagingService.this, 0, notificationIntent, 0);
NotificationCompat.Builder mBuilder = new NotificationCompat.Builder(this)
.setSmallIcon(R.mipmap.ic_launcher)
.setContentTitle(title)
.setContentText(body)
.setWhen(time)
.setPriority(Notification.PRIORITY_MAX)
.setDefaults(Notification.DEFAULT_LIGHTS| Notification.DEFAULT_SOUND)
.setContentIntent(pint);
NotificationCompat.BigTextStyle bigtext = new NotificationCompat.BigTextStyle();
bigtext.setBigContentTitle(title);
bigtext.bigText(body);
mBuilder.setStyle(bigtext);
if(!phone.equalsIgnoreCase("")){
mBuilder.addAction(android.R.drawable.ic_menu_call, "Call me!", pintCall);
}
notificationManager.notify(0, mBuilder.build());
}
Someone has a path on how to do this ?
Thanks.
The Firebase Notifications console sends so-called "notification messages". When your app is not in the foreground, these notifications messages are handled by the system itself and automatically displayed in the notification tray in the format you're seeing. When the user clicks this notification, the app is activated.
To ensure the message always gets delivered to your onReceiveMessage method, use "data messages".
For a great explanation, see the documentation on the different message types.