I wrote the following method to check if a notification is active (visible on the status bar):
public static boolean isNotificationActive(Context context, int id) {
Intent intentPopup = new Intent(context, PopupActivity.class);
PendingIntent test = PendingIntent.getActivity(context, id, intentPopup, PendingIntent.FLAG_NO_CREATE);
return test != null;
}
I create a PendingIntent exactly like the one I want to be checked (the same 'intentPopup' and 'id' are passed to this PendingIntent) and, because of FLAG_NO_CREATE, I expect this PendingIntent to be null if it doesn't exist yet. I read about this method in a thread posted years ago here.
If the notification has not yet been issued, the method returns the expected value (false). When the notification is issued and is in the status bar, the method returns true.
However, after I dismiss the notification, the method still returns true, as if the PendingIntent is still there.
What am I missing here? Is the PendingIntent still available or am I misunderstanding something?
Is there a better way to check if a specific notification is active (being displayed in the status bar)?
EDIT: here's the code that creates the notification:
Intent intentPopup = new Intent(context, PopupActivity.class);
intentPopup.putExtra("id", id);
intentPopup.putExtra("timeQ", timeQ);
PendingIntent pendingIntentPopup = PendingIntent.getActivity(context, id, intentPopup, PendingIntent.FLAG_UPDATE_CURRENT);
NotificationCompat.Builder mBuilder = new NotificationCompat.Builder(context)
.setContentIntent(pendingIntentPopup)
.setSmallIcon(R.drawable.q_notification_icon)
.setContent(contentView)
.setSound(Uri.parse("android.resource://" + context.getPackageName() + "/raw/notification_sound"))
.setVibrate(vibrate_pattern);
Notification notification = mBuilder.build();
notification.flags |= Notification.FLAG_NO_CLEAR;
NotificationManager notificationManager = (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE);
notificationManager.notify(id, notification);
Unfortunately PendingIntents that you embed in a Notification do not automatically disappear when the Notification is dismissed, viewed, or canceled. You can't use the presence or absence of a PendingIntent (using PendingIntent.FLAG_NO_CREATE like you've done) to determine whether or not a Notification is active.
To determine if a Notification is active, you can call NotificationManager.getActiveNotifications(). This will return all active Notifications that your app has posted.
Related
I have implemented smooch. https://smooch.io/
And my issue is that when I get the notification from smooch. If I'm in the background, I set a "unread messages" long that I use in my main activity on the smooch button.
The issue is that when I press on the notification, and the ConversationActivity is started from there. I need to set the unread messages to 0, because the ConversationActivity is opened. How can I know when this happens?
I cannot modify ConversationActivity.class from the smooch library.
I thought about making the notification myself, and changing the smooch created one with this one using this code:
private static void generateNotificationSmooch(final Context context, String title, String message) {
if (title == null)
title = context.getString(R.string.passenger_name);
Intent notificationIntent = new Intent(context, ConversationActivity.class);
notificationIntent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_ACTIVITY_SINGLE_TOP | Intent.FLAG_ACTIVITY_NEW_TASK);
int iUniqueId = (int) (System.currentTimeMillis() & 0xfffffff);
PendingIntent intent = PendingIntent.getActivity(context, iUniqueId, notificationIntent, PendingIntent.FLAG_UPDATE_CURRENT);
NotificationCompat.Builder mBuilder = new NotificationCompat.Builder(context);
mBuilder.setContentTitle(title).setContentText(message).setSmallIcon(R.drawable.notification_icon);
mBuilder.setContentIntent(intent);
Notification notification = mBuilder.build();
notification.flags |= Notification.FLAG_AUTO_CANCEL;
NotificationManager notificationManager = (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE);
notificationManager.notify(0, notification);
}
But I need to set the unread to 0 when the notification is pressed, and not when I create the notification. And I can't put it in pending intent
You have a few options.
Use the onSmoochShown delegate callback.
This callback will be triggered when the conversation is shown, so you will be able to update your unread count.
Use the onUnreadCountChanged delegate callback
.
This delegate will be called whenever the unread count changes for current user. You can use this callback to update your long accordingly.
Since you will need to be listening to these delegate callbacks when a notification is tapped, it may be best to set your delegate in your Application’s onCreate, after you initialize Smooch.
I researched and the only answers I could find either told:
How to disable the notification bar from being pulled down.
How to cancel a notification using:
NotificationManager notificationManager = (NotificationManager)context.getSystemService(Context.NOTIFICATION_SERVICE);
notificationManager.cancel(0);
Both of these aren't what I require as the notification gets cancelled fine. I've set two actions in my notification: 'Dismiss' and 'Open Activity'. As the name implies, upon clicking both, the above code executes and clears the notification but doesn't cause the notification bar from going back up. This is needed, specially when the second Notification Action causes an Activity launch.
I tried on Android Lollipop and Nougat and the notification bar didn't go back up in either. So if someone could kindly tell me if it is even possible and how.
Thanks.
The code for building the notification:
NotificationCompat.Builder builder = new NotificationCompat.Builder(this);
builder
.setSmallIcon(icon).setTicker(message).setWhen(when)
.setAutoCancel(true).setContentTitle("Kindly record your Voice")
.setColor(Color.RED);
notificationIntent = new Intent(this,ReminderReceiver.class);
notificationIntent.setAction("Record");
PendingIntent pendIntent1 = PendingIntent.getBroadcast(getApplicationContext(), 1, notificationIntent, PendingIntent.FLAG_UPDATE_CURRENT);
builder.addAction(R.drawable.common_google_signin_btn_icon_dark, "Record", pendIntent1);
notificationIntent2 = new Intent(this, ReminderReceiver.class);
notificationIntent2.setAction("Dismissed");
PendingIntent pendIntent2 = PendingIntent.getBroadcast(getApplicationContext(), 1, notificationIntent2, PendingIntent.FLAG_UPDATE_CURRENT);
builder.addAction(R.drawable.starticon, "Dismiss", pendIntent2);
notificationIntent3 = new Intent(this, CancelReceiver.class);
PendingIntent pendIntent3 = PendingIntent.getBroadcast(getApplicationContext(), 1, notificationIntent3, PendingIntent.FLAG_UPDATE_CURRENT);
builder.setDeleteIntent(pendIntent3);
notification = builder.build();
notification.flags |= Notification.FLAG_AUTO_CANCEL;
notificationManager.notify(1, notification);
Might seem weird, but the notification bar doesn't go up when there are other notifications present. If yours is the only notification, the bar slides up automatically upon clicking.
Notification setAutoCancel(true) doesn't work if clicking on Action
I have a notification with an action within it. When I tap on the notification it gets removed from the list. However, when I click on the Action it successfully completes the Action (namely makes a call), but when I return to the list of notifications, it remains there.
Relative code of the AlarmReceiver:
public class AlarmReceiver extends BroadcastReceiver {
Meeting meeting;
/**
* Handle received notifications about meetings that are going to start
*/
#Override
public void onReceive(Context context, Intent intent) {
// Get extras from the notification intent
Bundle extras = intent.getExtras();
this.meeting = extras.getParcelable("MeetingParcel");
// build notification pending intent to go to the details page when click on the body of the notification
Intent notificationIntent = new Intent(context, MeetingDetails.class);
notificationIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
notificationIntent.putExtra("MeetingParcel", meeting); // send meeting that we received to the MeetingDetails class
notificationIntent.putExtra("notificationIntent", true); // flag to know where the details screen is opening from
PendingIntent pIntent = PendingIntent.getActivity(context, 0, notificationIntent, 0);
// build intents for the call now button
Intent phoneCall = Call._callIntent(meeting);
if (phoneCall != null) {
PendingIntent phoneCallIntent = PendingIntent.getActivity(context, 0, phoneCall, PendingIntent.FLAG_CANCEL_CURRENT);
int flags = Notification.FLAG_AUTO_CANCEL;
// build notification object
NotificationCompat.Builder builder = new NotificationCompat.Builder(context);
Notification notification = builder.setContentTitle("Call In")
.setContentText(intent.getStringExtra("contextText"))
.setTicker("Call In Notification")
.setColor(ContextCompat.getColor(context, R.color.colorBluePrimary))
.setAutoCancel(true) // will remove notification from the status bar once is clicked
.setDefaults(Notification.DEFAULT_ALL) // Default vibration, default sound, default LED: requires VIBRATE permission
.setSmallIcon(R.drawable.icon_notifications)
.setStyle(new NotificationCompat.BigTextStyle()
.bigText(meeting.description))
.addAction(R.drawable.icon_device, "Call Now", phoneCallIntent)
.setCategory(Notification.CATEGORY_EVENT) // handle notification as a calendar event
.setPriority(Notification.PRIORITY_HIGH) // this will show the notification floating. Priority is high because it is a time sensitive notification
.setContentIntent(pIntent).build();
notification.flags = flags;
// tell the notification manager to notify the user with our custom notification
NotificationManager notificationManager = (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE);
notificationManager.notify(0, notification);
}
}
}
use this flag:
Notification.FLAG_AUTO_CANCEL
inside this:
int flags = Notification.FLAG_AUTO_CANCEL;
Notification notification = builder.build();
notification.flags = flags;
Documentation
Ok turns out it's a known problem already, and it needs extra code to be done (keeping reference to notification through id). Have no clue why API does not provide this, as it seems very logical to do. But anyways,
see this answer in stackoverflow:
When you called notify on the notification manager you gave it an id - that is the unique id you can use to access it later (this is from the notification manager:
notify(int id, Notification notification)
To cancel, you would call:
cancel(int id)
with the same id. So, basically, you need to keep track of the id or possibly put the id into a Bundle you add to the Intent inside the PendingIntent?
I faced this problem today, and found that FLAG_AUTO_CANCEL and setAutoCanel(true), both work when click on notification,
but not work for action click
so simply, in the target service or activity of action, cancel the notification
NotificationManager manager = (NotificationManager) this.getSystemService(Context.NOTIFICATION_SERVICE);
manager.cancelAll();
or if have more notification
manager.cancel(notificationId);
You have created two pending intent use in boths and change Flag too.
PendingIntent pIntent = PendingIntent.getActivity(context, (int) System.currentTimeMillis(), notificationIntent, 0);
PendingIntent phoneCallIntent = PendingIntent.getActivity(context, (int) System.currentTimeMillis(), phoneCall, PendingIntent.FLAG_UPDATE_CURRENT);
// CHANGE TO THIS LINE
PendingIntent pIntent = PendingIntent.getActivity(context, 0, notificationIntent, 0);
PendingIntent phoneCallIntent = PendingIntent.getActivity(context, 0, phoneCall, PendingIntent.FLAG_CANCEL_CURRENT);
Is it possible not launch new activity if we receive a push notification while the app is running?
My activity works with fragments and I want to do transition to a determinate fragment when the notification is received. My activity have data that I need to show the fragments. The problem is that when I receive the push notification while the app is running the method onDestroy is called and here I clear the data and then the app crash because the data are null. How can I do to not create new activity when the app receive a push notification while is running? In case the app is running I want that if you click the notification do a transition fragment, not create again the activity.
Thanks in advance.
First of all, I think that you mean "notification" to be a "message", but not android.app.Notification class.
And second, I don't think it's a best practise to raise new GUI when receiving a message, which would interrupt the user interaction. For details, please refer to: http://developer.android.com/training/notify-user/index.html and http://developer.android.com/design/patterns/notifications.html.
At last, if you really wanna do what you stated in your thread, I wonder why the data used to generate the show-data fragment is held in the activity. Try holding the data in an android.app.IntentService object, and then generate transfer the data to new activity, and then use android.app.Fragment.setArguments method to transfer the data from activity to fragment.
I think that this code will help you. This which you need is PendingIntent, it make transaction to desired activity.
/**
* Issues a notification to inform the user that server has sent a message.
*/
private static void generateNotification(Context context, String title,
String message) {
//get the default notification sound URI
Uri uriNotificationSound = RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION);
//make intent to the application. if the application is opened just maximize it.
Intent homeIntent = new Intent(context, 'your desired activity');
homeIntent.addFlags(Intent.FLAG_ACTIVITY_REORDER_TO_FRONT);
PendingIntent contentIntent = PendingIntent.getActivity(context, 0,
homeIntent, 0);
NotificationCompat.Builder mBuilder =
new NotificationCompat.Builder(context)
.setSmallIcon(R.drawable.ic_launcher)
.setContentTitle("eCommCongress")
.setContentText(message)
.setLights(Color.GREEN, 1500, 1500)
.setSound(uriNotificationSound)
.setAutoCancel(true)
.setContentIntent(contentIntent);
NotificationManager mNotificationManager =
(NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE);
// mId allows you to update the notification later on.
mNotificationManager.notify(counter, mBuilder.build());
counter++;
}
It is perfectly possible and I do such a thing in one of my apps. First, you need to declare your activity as android:launchMode="singleTop",
Then, when you build you must configure your pending intent not to fire a new instance of your activity:
mNotificationManager = (NotificationManager)
this.getSystemService(Context.NOTIFICATION_SERVICE);
Intent intent = new Intent("YOUR ACTION HERE");
intent.setClassName(this, MainActivity.class.getName());
intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_ACTIVITY_SINGLE_TOP);
PendingIntent resultPendingIntent = PendingIntent.getActivity(getApplicationContext(), 0, intent, PendingIntent.FLAG_CANCEL_CURRENT);
NotificationCompat.Builder mBuilder = new NotificationCompat.Builder(this);
mBuilder.setContentIntent(resultPendingIntent);
Notification notification = mBuilder.build();
notification.defaults |= Notification.DEFAULT_VIBRATE | Notification.DEFAULT_LIGHTS;
notification.flags |= Notification.FLAG_SHOW_LIGHTS | Notification.FLAG_AUTO_CANCEL;
mNotificationManager.notify(idNotificacion,notification);
Now all you have to do is to override your onNewIntent inside your Activity and do whatever you want with your fragment:
#Override
protected void onNewIntent(Intent intent) {
MiLog.i(getApplicationContext(),"IntentShit","new intent received");
MiLog.i(getApplicationContext(),"IntentShit","Action: "+intent.getAction());
if(intent.getAction()!=null && intent.getAction().equals("YOUR ACTION HERE"){
//DO your stuff here
}
}
You should also take a look at this page for more info:
http://www.intridea.com/blog/2011/6/16/android-understanding-activity-launchmode
I'm currently doing some notifications for my app. Now I've successfully created a notification but problem is that each of my notification doesn't pass different extras on click.
Well what happen is that I only have a loop that calls the createNotification method per loop and also I assign different ID's for those for the notification to appear in different stack.
here's my code:
private void createNotification(String record_name, String file_path, String status, int id) {
/*must pass:
* record_name, (get the record name in DB using the id create a new query method)
* record_status, (simple part just match if equivalent to ready to download for the JSON data then show notif if true)
* record_path *full path* (this one can be get using the record name itself add the path and extension name)*/
/*this will jump from the current activity into the target activity class just do some workarounds here*/
Intent intent = new Intent(this, RecordEditActivity.class);
intent.putExtra("record_name", record_name);
intent.putExtra("record_path", file_path);
intent.putExtra("record_status", status);
PendingIntent pIntent = PendingIntent.getActivity(this,0, intent, 0);
/*build the notification here this is only supported for API 11. Since we've targeted API 11 there will be no problem on this*/
NotificationCompat.Builder notify = new NotificationCompat.Builder(this)
.setContentTitle(record_name + " is ready for download")
.setContentText("Click to view or download recording")
.setAutoCancel(true)
.setSmallIcon(R.drawable.notif_icon)
.setLargeIcon(BitmapFactory.decodeResource(this.getResources(), R.drawable.ic_launcher))
.setTicker("Echo: your file is ready for download")
.setContentIntent(pIntent);
NotificationManager notificationManager = (NotificationManager) getSystemService(NOTIFICATION_SERVICE);
if(Build.VERSION.SDK_INT<16){
/*build notification for HoneyComb to ICS*/
notificationManager.notify(id, notify.getNotification());
}if(Build.VERSION.SDK_INT>15){
/*Notification for Jellybean and above*/
notificationManager.notify(id, notify.build());
}
}
I think the problem is in the PendingIntent part since I don't know which flags should I use for this but I'm not that sure about it.
Got it! what needed is for me to assign an ID for my pendingIntent requestCode what I did is assign the same ID I used for my notificationManager.
More info here.
Just use this one line of code-
PendingIntent.getActivity(context, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT);
And for more detail see this answer:
GCM android Push Notification shows old message always. Intent received incorrect