I have a service that shows a notification PendingIntent each time it receives a new GCM message. The problem is that the GCM messages can be of different kinds. And if many notifications leave unread, I want not to show them separately but in groups like:
you have 3 unread messages of type A
you have 2 unread messages of type B
you have 4 unread messages of type C
As far as I understand, to get this effect I need to have an access to unread/unseen notifications. Each time when I new notification comes I can check, if there is another unread message of this type, and then decide, whether I create a new notification or update an old one.
My question is: is there a way to see, which notifications are unseen and get access to them?
For any case this is my method to create a message; if an argument notificationId is 0 a new notification should be created. Else - updated.
private int sendNotification(String msg, Integer notificationId) {
Log.d(TAG, "sending message with text: "+msg);
mNotificationManager = (NotificationManager)
this.getSystemService(Context.NOTIFICATION_SERVICE);
Random random = new Random();
int notification_id = notificationId==0?random.nextInt(9999 - 1000) + 1000:notificationId;
RemoteViews remoteViews = new RemoteViews(getPackageName(),
R.layout.notification);
Intent intent = new Intent(this, MainActivity.class);
// Send data to NotificationView Class
intent.putExtra("text", msg);
PendingIntent pending= PendingIntent.getActivity(getApplicationContext(), 0, intent, PendingIntent.FLAG_UPDATE_CURRENT);
NotificationCompat.Builder mBuilder =
new NotificationCompat.Builder(this)
.setSmallIcon(R.drawable.ic_launcher)
.setContentTitle("escos")
.setStyle(new NotificationCompat.BigTextStyle()
.bigText(msg))
.setContentText(msg);
mBuilder.setContentIntent(pending);
mBuilder.setContent(remoteViews);
remoteViews.setTextViewText(R.id.notiftext, msg);
remoteViews.setImageViewResource(R.id.notifim, R.drawable.ic_launcher);
Notification notification = mBuilder.build();
notification.flags |= Notification.FLAG_AUTO_CANCEL;
notification.sound = RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION);
mNotificationManager.notify(notification_id, notification);
return notification_id;
}
For different Notification strip (A, B, C etc.) in your status bar, use different NOTIFICATION_ID for building the Notification on basis of your defined type or collapse_key received from GCM.
For determining unread and read messages, use a local variable (counter) in Shared Preferences and increment it each time a specific type of Notification comes (on basis of defined type or collapse_key).
Then generate the Notification with that particular NOTIFICATION_ID as Notification with particular NOTIFICATION_ID can override each other. So You can override the previous Notification with Iterative Numbered text in New Notification.
As soon as user click on any Notification or particular Notification, clear the notification and reset the value of (counter) in Shared Preferences.
Edit1 : When you click on Notification with particular Pending Intent, then in that Activity use this code for removing all the Notifications generated from your app :
NotificationManager nMgr = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
try {
nMgr.cancelAll();
} catch (Exception e) {
e.printStackTrace();
}
Note : Do remember to add Try-Catch before you call cancelAll() as cancelAll() may not be supported by the device model and will generate
java.lang.SecurityException: Permission Denial
error.
Edit 2:
You can also use nMgr.cancel(NOTIFICATION_ID); to clear a specific notification, pass NOTIFICATION_ID to particular intent via extras and get the extras in that activity to cancel a particular notification.
And as you click on any notification it will be cleared from status bar unless you have not set .setAutoCancel(false) in your Notification Builder.
Related
Short version:
I want to create a notification that is uninterruptible by all other notifications, SMS messages, etc until the user clears it.
Long version:
I'm using Firebase Cloud Messaging to send alerts to my phone. Messages are handled based on the topic, and I need to make the "alarm" messages repeat continuously until the notification is cleared by the user. This is currently accomplished by setting the notification with FLAG_INSISTENT, which loops the sound.
The problem is the insistent "alarm" notification is permanently stopped when a different notification or SMS comes through.
I would like to ignore all new notifications, or restart the alarm after the new notification plays. I've searched for a couple hours and tried several flags and settings, but can't figure out how to do it.
Here is the code I'm using to handle FCM messages and set the notifications:
public class MyFirebaseMessagingService extends FirebaseMessagingService {
#Override
public void onMessageReceived(RemoteMessage remoteMessage) {
if (remoteMessage.getData() != null){
String messageTopic= remoteMessage.getFrom();
String messageTitle = remoteMessage.getData().get("title");
String messageBody = remoteMessage.getData().get("message");
if (messageTopic.equals("/topics/news")) {
Intent intent = new Intent(this, MainScreenActivity.class);
intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK);
PendingIntent pendingIntent = PendingIntent.getActivity(this, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT);
Uri soundUri= RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION);
NotificationCompat.Builder notificationBuilder = new NotificationCompat.Builder(this)
.setSmallIcon(R.drawable.ic_stat_news)
.setContentTitle(messageTitle)
.setContentText(messageBody)
.setAutoCancel(true)
.setSound(soundUri)
.setContentIntent(pendingIntent)
.setPriority(Notification.PRIORITY_MAX);
NotificationManager notificationManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
notificationManager.notify(30548, notificationBuilder.build());
}
else if (messageTopic.equals("/topics/alarm")) {
Intent intent = new Intent(Intent.ACTION_VIEW);
intent.setData(Uri.parse("http://www.example.com/alarm.php"));
PendingIntent pendingIntent = PendingIntent.getActivity(this, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT);
Uri soundUri = RingtoneManager.getDefaultUri(RingtoneManager.TYPE_ALARM);
NotificationCompat.Builder notificationBuilder = new NotificationCompat.Builder(this)
.setSmallIcon(R.drawable.ic_stat_alarm)
.setContentTitle(messageTitle)
.setContentText(messageBody)
.setAutoCancel(true)
.setSound(soundUri)
.setContentIntent(pendingIntent)
.setPriority(Notification.PRIORITY_MAX);
Notification mNotification = notificationBuilder.build();
mNotification.flags |= Notification.FLAG_INSISTENT;
NotificationManager notificationManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
notificationManager.notify(30549, mNotification);
}
}
}
I may be able to prevent my own notifications from interrupting the alarm by ignoring them when the alarm notification ID (30549) is active (or create the new notification and then create the alarm again). However, SMS and notifications from other programs will still interrupt, so that wouldn't be a perfect solution.
I don't think you'll have luck with this, unfortunately. Android will not let you have a notification that takes full priority from my understanding.
However, in the Firebase console when you go to the notifications section and click advanced you can set the priority of a notification to High and set a sound.
Since it looks like you're writing the notification programmatically and setting priority to Max this will achieve the same affect.
Setting priority to high, from Google's documentation:
When a high-priority notification arrives (see right), it is presented to users for a short period of time with an expanded layout exposing possible actions.
After this period of time, the notification retreats to the notification shade. If a notification's priority is flagged as High, Max, or full-screen, it gets a heads-up notification
Also check out this SO for someone who's notification wouldn't go away when they wanted it to
here
My app sends notifications but the problem is that if there are some notification pending in the action bar, I want to update the message adding the new message to the old message.
For example, if the message is Hi!, and the device receive another message (Pamela) before the user has opened the old message, I want to show only one notification with the message Hi! Pamela.
My code for send notifications is:
int icon = R.drawable.ic_launcher;
long when = System.currentTimeMillis();
NotificationManager notificationManager = (NotificationManager) this
.getSystemService(Context.NOTIFICATION_SERVICE);
Notification notification = new Notification(icon, msg, when);
String title = this.getString(R.string.app_name);
Intent notificationIntent = new Intent(getApplicationContext(),
FirstActivity.class);
notificationIntent.putExtra("message", msg);
notificationIntent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP
| Intent.FLAG_ACTIVITY_SINGLE_TOP);
int notifyID = 1;
PendingIntent intent = PendingIntent.getActivity(this, notifyID,
notificationIntent, PendingIntent.FLAG_UPDATE_CURRENT);
notification.setLatestEventInfo(this, title, msg, intent);
notification.flags |= Notification.FLAG_AUTO_CANCEL;
notificationManager.notify(0, notification);
Is it possible to get the old message of PendingIntent?
Thanks in advance.
One way to do this is to concatenate the string, by saving what is already displayed like, before the following is called for the first time:
notificationIntent.putExtra("message", msg);
//save "Hi" , concat "Pamela" update the notification with the same notification id
You save the string msg, then concatenate the string that you receive in the next notification. However, to identify, which notifications contain parts of String to be concatenated, is required in this case. Either you can set prefixes to messages or identify by notification id.
Not the ideal way to do it i feel, but can't think of anything else.
It's not possible to retrieve the existing notification from the NotificationManager. You need to keep track of it yourself independently of the notification, and save the unread messages somewhere else (maybe in a SQLite Database or SharedPreferences file).
You will need to determine if the user swipes away the notification, which means you will have to use the NotificationCompat.Builder class to create the notification. You can use the setDeleteIntent method to supply an Intent to trigger when the notification is swiped away, at which point you delete the old messages from wherever you are storing them so that a new message will show a notification with only the new message.
I am trying to Notify user based on some criteria. Multiple Notifications are being shown in Status Bar but I want to Group the notification in single notification and when user clicks in the Status Bar, I want to retrieve all notifications in that group. Is that possible? Or I have to maintain PendingIntents of those notifications? Any help will be appreciated. For example, if birthdays of two friends come on same day, then 2 notifications should be shown. I want to combine these notifications i.e. instead of 2 notifications in the status bar, I want one, when user clicks on it, it should have information about 2 notifications. Is it possible?
Please see the code below for displaying notifications.
public void displayNotification(BirthdayDetail detail)
{
NotificationCompat.Builder builder = new NotificationCompat.Builder(this.context);
builder.setSmallIcon(R.drawable.ic_launcher);
builder.setContentTitle(detail.getContactName());
builder.setContentText(detail.getContactBirthDate());
Intent resultIntent = new Intent(this.context, NotificationView.class);
resultIntent.putExtra("name", detail.getContactName());
resultIntent.putExtra("birthdate", detail.getContactBDate());
resultIntent.putExtra("picture_path", detail.getPicturePath());
resultIntent.putExtra("isContact", detail.isFromContact());
resultIntent.putExtra("notificationId", notificationId);
if(detail.isFromContact())
{
resultIntent.putExtra("phone_number", detail.getPhoneNumber());
}
PendingIntent resultPendingIntent = PendingIntent.getActivity(this.context, requestCode++,
resultIntent, PendingIntent.FLAG_UPDATE_CURRENT);
builder.setContentIntent(resultPendingIntent);
notificationManager
= (NotificationManager) this.context.getSystemService(Context.NOTIFICATION_SERVICE);
notificationManager.notify(notificationId, builder.build());
notificationId++;
}
When you need to issue a notification multiple times for the same type
of event, you should avoid making a completely new notification.
Instead, you should consider updating a previous notification, either
by changing some of its values or by adding to it, or both.
You can use something like:
mNotificationManager =
(NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
// Sets an ID for the notification, so it can be updated
int notifyID = 1;
mNotifyBuilder = new NotificationCompat.Builder(this)
.setContentTitle("New Message")
.setContentText("You've received new messages.")
.setSmallIcon(R.drawable.ic_notify_status)
numMessages = 0;
// Start of a loop that processes data and then notifies the user
...
mNotifyBuilder.setContentText(currentText)
.setNumber(++numMessages);
// Because the ID remains unchanged, the existing notification is
// updated.
mNotificationManager.notify(
notifyID,
mNotifyBuilder.build());
Source: http://developer.android.com/training/notify-user/managing.html
I have a server with some data and in my app I want to show this data via push-notification, so the problem is I didn't get how to cooperate notification number in status bar with my notifiŅations. In my app I get notifications as ArrayList from my server. For each notification I should use a "Notification builder", in which I'll put notify fields like icon, name, desc etc, and at least I should call "NotificationManager.notify" for each of them, but how I can show that I've just gotten 3 messages for example in my status bar(one icon with indicator of 3, NOT 3 icons), and don't multiply a notification sound, but still show all of them when I open a status bar.
My code:
public void sendNotifications(ArrayList<Message> messages){
int notifyID = 0;
mNotificationManager = (NotificationManager) getSystemService(NOTIFICATION_SERVICE);
for(Message message:messages){
Intent notificationIntent = new Intent(getApplicationContext(), MainActivity.class);
PendingIntent contentIntent = PendingIntent.getActivity(getApplicationContext(),0, notificationIntent,
PendingIntent.FLAG_CANCEL_CURRENT);
Resources res = getApplicationContext().getResources();
Notification.Builder builder = new Notification.Builder(getApplicationContext());
builder.setContentIntent(contentIntent)
.setSmallIcon(R.drawable.ic_launcher)
.setLargeIcon(BitmapFactory.decodeResource(res, messages.media))
.setTicker("Got a new message")
.setWhen(System.currentTimeMillis())
.setAutoCancel(true)
.setContentTitle(message.titile)
.setContentText(message.text);
Notification notification = builder.getNotification();
mNotificationManager.notify(notifyID, notification);
notifyID++;
}
}
UPD
For more understanding what i want to i've added an images
-pic1 When i send notifications - icon shows me how much i got
-pic2 When i opened a status bar it shows me all my notifies
It is possible to do that?
You cannot do that - Combine 3 notification into one.
Either you create a single notification combining all the notifications or like this only.
It is not necessary that you will get 3 notifications. You can get 1 or 2 also.
I don't see the issue here. If there are 3 notifications, you will see 3 icons in the status bar.
Each icon represents an entry in the pull down notification bar- having one icon represent multiple entries wouldn't really make sense.
Notification.Builder has method setNumber to set number of notifications. It's described in Notification docs in Updating notifications section.
You can use Big view notification.
Check here : Notifications
Notification Id must be a constant. If notification id is different it will show as different notifications. So your code must be like this, declare ID and count as field variable:
public static final int NOTIFICATION_ID = 1;
private int notificationCount = 1;
and change the method like this:
public void sendNotifications(ArrayList<Message> messages){
int notifyID = 0;
mNotificationManager = (NotificationManager) getSystemService(NOTIFICATION_SERVICE);
for(Message message:messages){
Intent notificationIntent = new Intent(getApplicationContext(), MainActivity.class);
TaskStackBuilder stackBuilder = TaskStackBuilder.create(this);
// Adds the back stack
stackBuilder.addParentStack(MainActivity.class);
// Adds the Intent to the top of the stack
stackBuilder.addNextIntent(notificationIntent);
// Gets a PendingIntent containing the entire back stack
PendingIntent contentIntent = stackBuilder.getPendingIntent(0,
PendingIntent.FLAG_CANCEL_CURRENT);
Resources res = getApplicationContext().getResources();
Notification.Builder builder = new Notification.Builder(getApplicationContext());
builder.setContentIntent(contentIntent)
.setSmallIcon(R.drawable.ic_launcher)
.setLargeIcon(BitmapFactory.decodeResource(res, messages.media))
.setTicker("Got a new message")
.setWhen(System.currentTimeMillis())
.setAutoCancel(true)
.setContentTitle(message.titile)
.setContentText(message.text);
.setNumber(notificationCount++);
mNotificationManager.notify(NOTIFICATION_ID, builder.build());
}
}
Thanks
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