I have an app with several activities. I am implenting Firecbase FCM and it all works pretty well except in handling which activity to go to when the user clicks on the notification icon when it is received.
As I'm not sure how/when the FirebaseMessagingService is instantiated I cannot set it up with access to any of my objects. The only thingI have been able to do is to store the current Activity in the App as
public static Activity CurrentActivity { get; set; }
I then set the above in the OnCreate() of each activity, then in FirebaseMessagingService .OnMessageReceived() I setup my pending intent as below:
Intent intent = new Intent(this, App.CurrentActivity.GetType());
intent.AddFlags(ActivityFlags.SingleTop);
var pendingIntent = PendingIntent.GetActivity(this, App.NOTIFICATION_ID, intent, PendingIntentFlags.OneShot);
var notificationBuilder = new NotificationCompat.Builder(this, App.CHANNEL_ID)
.SetSmallIcon(Resource.Drawable.ic_notification)
.SetContentTitle("FCM Message")
.SetContentText("test")
.SetAutoCancel(true) //dismisses the notification on click
.SetContentIntent(pendingIntent);
var notificationManager = NotificationManagerCompat.From(this);
notificationManager.Notify(App.NOTIFICATION_ID, notificationBuilder.Build());
This works in so far so when the user clicks on the Notification it goes to the correct activity.
The problem is if a notification is recevied when the user is in Activity A but doesn't click on it and moves to Activity B and then clicks on the notification. My Pending Intent will be Activity A. However after the Notification is shown, Activity A is then displayed.
I was thinking if it is possible in OnMessageReceived() to detect is the app is in foreground or background then if in foreground I could just do and intent to display an Alert Dialog of the message and if in background then my original code would work fine.
Does anyone have any idea if this is possible and how?
I have managed to sort this out so thought I would post an update for anyone else who has a similar problem.
In my FirebaseMessagingService.OnMessageReceived() I created a PendingIntent to a standard activity called NotificationActivity.
public override void OnMessageReceived(RemoteMessage message)
From message I extracted the body and title and passed to NotificationActivity
NotificationActivity.OnCreate() will then just display an AlertDialog and on the OK click I closed the activity using this.Finish()
This works perfectly when the user receives a notification when in the app. The user can click on the notification and it will show the AlertDialog. On close it just resumes on whatever was the current activity.
Related
I have 5 activities in my app. Every activity starts the same foreground service.
In onStartCommand method of the service foreground notification is created which unfortunately means that every call of startForegroundService() in any activity plays notification sound (even though the service is already running). How can I create the foreground notification only once or at least how not to play notification sound on successive startForegroundService() calls?
The other related question is: how can I go back to my application when I click the foreground notification? I have 5 activites and I would like to reopen the activity that was the last one the user was interacting with.
#1. before starting the service just check if its already running or not. In that case this will help you https://stackoverflow.com/a/5921190/6413387
#2. To reopen your last opened activity, you need to update the pending intent of your notification. Hope you will find your answer here https://stackoverflow.com/a/20142620/6413387
How can I create the foreground notification only once or at least how not to play notification sound on successive startForegroundService() calls?
You can check if the notification is already visible and show it only if it's not visible. You need to have a reference to the notification PendingIntent and notificationId.
fun isNotificationVisible(context: Context, notificationIntent: Intent, notificationId: Int): Boolean {
return PendingIntent.getActivity(context, notificationId, notificationIntent, PendingIntent.FLAG_NO_CREATE) != null
}
how can I go back to my application when I click the foreground notification?
You need a PendingIntent to open the app from a notification. To open the last activity shown you can remember this using Preferences in the onResume() method of each activity and route the notification into a routing activity that starts the right activity according to the value saved into the preferences.
val intent = Intent(context, RouteActivity::class.java)
val notificationBuilder = NotificationCompat.Builder(context, channelId)
.setContentIntent(intent)
val notificationManager = NotificationManagerCompat.from(context)
val notification = notificationBuilder.build()
notificationManager.notify(notificationId, notification)
Another way to do this is to update the notification PendingIntent if it's already visible with the last activity shown. In this case you don't have to store any value on Preferences and you don't need a route activity.
I have this scenario when user clicks the notification then, if the app is opened/foreground I want to redirect the user to HomeActivity else redirect the user to SplashActivity as I am performing some authentication tasks there. So, what is the best and proper way to achieve this??
I know there are lot of related questions but I haven't found anything specific to my usecase
To redirect the user to a specific Activity based on your logic you can use PendingIntent.
To check a working example click here.
OR
try below code on button click.
NotificationCompat.Builder builder = new NotificationCompat.Builder(this);
builder.setSmallIcon(android.R.drawable.ic_dialog_alert);
Intent intent = new Intent(Intent.ACTION_VIEW, Uri.parse("https://www.stackoverflow.com/"));
PendingIntent pendingIntent = PendingIntent.getActivity(this, 0, intent, 0);
builder.setContentIntent(pendingIntent);
builder.setLargeIcon(BitmapFactory.decodeResource(getResources(), R.mipmap.ic_launcher));
builder.setContentTitle("Notifications Title");
builder.setContentText("Your notification content here.");
builder.setSubText("Tap to view the website.");
NotificationManager notificationManager = (NotificationManager) getSystemService(NOTIFICATION_SERVICE);
// Will display the notification in the notification bar
notificationManager.notify(1, builder.build());
To check if your app is in the foreground or not Check out this post.
After some searching in this forum I got this post , taking some guidance from that I figured out a solution, on notification click I am redirecting every intent to HomeActivity and in onCreate() put my code to check if authentication is done or not(before setContentView()). If the authentication is not done redirect to SplashActivity and finish the current activity, otherwise continue.
Help me out friends I have been facing a problem from a week
I have made an android app in which I got 3 activities named
MainActivity
NotificationListActivity
NotificationActivity
other than that I have 2 services in my app ( as because I am using FCM )
JLZFirebaseMsgService
JLZInstanceIdService
in JLZFirebaseMsgService.java I have written the code
private void sendNotification(String messageBody) {
Intent intent = new Intent(this,NotificationActivity.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("Jee Lo Zindagi 2.0")
.setContentText(messageBody)
.setAutoCancel(true)
.setSound(defaultSoundUri)
.setContentIntent(pendingIntent);
NotificationManager notificationManager =
(NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
notificationManager.notify(0, notificationBuilder.build());
}
what I want is to whenever FCM server sends the notification to the devices the app should open NotificationActivity as the I wrote
but whenever I tap on the notification it opens the MainActivity I don't know why.
when the app is open the notification comes and by tapping on it we go to the NotificationActivity that's what I wanted but not the same scenario when the app is closed.
but sometimes it happens that the app shows the correct activity by tapping on the notification I still don't know why.
You should use "data" insted of "notification" on your server code
When you use "notification" on your server code
while you app is not running the JLZFirebaseMsgService.java does not start . instead the you will recevie a notification with your launcher icon
But if you use "data" on your server code your messaging service will start
It seems that you are sending a notification messages, these are messages that go to onMessageReceived when your app is in the foreground in your case that will result in you manually generating a notification, when your app is in the background it will result in an auto-generated notification that your code does not define.
If you are using the FCM REST API then you can use the click_action field which would allow you to define which activity would be launched when the user taps on the notification. If you are using the Firebase console there currently you cannot specify a click_action from there.
I am using the following code showing the notification, it works properly. I am look for the listener from which i can come to know whether the notification is expanded or not.
I want to open the app if the notification is expanded or else open the particular activity of the app.
Intent intent= new Intent(context, Activity1.class);
PendingIntent pendingIntent = PendingIntent.getActivity(context, getNextRandom(), intent, 0);
Builder newBuilder newBuilder = new Notification.Builder(context);
newBuilder.setContentTitle(title)
.setContentText(subtitle)
.setAutoCancel(true)
.setSmallIcon(R.drawable.icon)
.setTicker(notificationMessage)
.setContentIntent(pendingIntent);
Notificationnotification = new Notification.BigTextStyle(newBuilder)
.setBigContentTitle(notificationTitle)
.bigText(text)
.build();
Let me know if there is way to acheive this?
There is no way to know if the notification is open... What you can do is add buttons to the expanded notification that pressing on them will act differently than pressing on the notification itself.
There maybe no direct way, but maybe the following hack can help!!
You can have a custom notification layout and use RemoteView, Set a setOnClickPendingIntent to launch a service for the entire view so that you get notified when the notification is clicked.
When the user clicks the notification, service is started and show the new expanded custom layout from the service (you replace the old notification with the new one)
Maybe show your initial notification also from the same service using startforeground, so that your app is not killed and the view click can be received faster since service is already running and response time for changing the view is lower.
see this for remoteview and this for launching service from notification click.
I have a method which receives text from a push notification, via the Parse API, and packages it into a notification object. Pretty standard stuff. My problem is that I'm trying to use a BigTextStyle to display my notification in the list, but it refuses to do so, and only shows one line of text and the two-finger gesture does not cause it to expand.
However, if I tap the notification, which opens the app, then return to the notification list, it is displayed in the BigTextStyle and is responsive to gestures. So, my guess is that somehow tapping on the notification is activating it and allowing the BigTextStyle code to kick in.
I like that tapping on the notification opens the app, but I don't want to force my users to open the app then close it again to see the full text of my messages. So is there a way I could either make the notification display in the BigTextStyle format from the start, or to make it so that the first click "activates" the notification, allowing the full message text to be seen, and then a second click opens the app? Any help would be appreciated.
Here is my code from the Notification method:
public void receiveNotification() {
NotificationCompat.BigTextStyle bts = new NotificationCompat.BigTextStyle();
bts.bigText(SplashActivity.globalDataString);
bts.setSummaryText("Tap to open app, swipe to dismiss message");
NotificationCompat.Builder m = new NotificationCompat.Builder(this);
m.setContentTitle("New Push Notification")
.setContentText(SplashActivity.globalDataString)
.setSmallIcon(R.drawable.app_icon)
.setStyle(bts)
.build();
Intent openApp = new Intent(this, MenuActivity.class);
// This ensures that navigating backward from the Activity leads out of
// the application to the Home screen.
TaskStackBuilder stackBuilder = TaskStackBuilder.create(this);
// Adds the back stack for the Intent (but not the Intent itself)
stackBuilder.addParentStack(MenuActivity.class);
// Adds the Intent that starts the Activity to the top of the stack
stackBuilder.addNextIntent(openApp);
PendingIntent resultPendingIntent =
stackBuilder.getPendingIntent(
0,
PendingIntent.FLAG_UPDATE_CURRENT
);
m.setContentIntent(resultPendingIntent);
NotificationManager mNotificationManager =
(NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
// mId allows you to update the notification later on.
mNotificationManager.notify(pushMessageID, m.build());
pushMessageID++;
//reset notification
flag1 = false;
}
EDIT: I think my problem is with where I'm calling my receiveNotification() method from. Right now I have it in the onCreate() method of my app's starting activity, which doesn't make much sense looking back. Should I put it in my broadcastReceiver class, or would there be a better place to put it?
Yes, the creation and display of the notification is usually done either in the broadcast receiver, or in an intent service started by the broadcast receiver. Only when the user taps the notification, the relevant activity is launched. You can see Google's client code sample here.