Prelude
I'm trying to add a chronometer on the notification. The chronometer is a service. Every second this line is called (continue Thread is a the "running" boolean, timeString is the elaborated String showing the time):
NotificationChrono.updateNotification(getApplicationContext(), continueThread,
NOTIF_ID, timeString, "Chronometer", notificationManager);
This is the NotificationChrono class:
public class NotificationChrono {
static public void updateNotification(Context context, boolean running,
int id, String title, String text,
NotificationManager notificationManager) {
Intent stopIntent = new Intent("com.corsalini.david.barcalc.STOP");
PendingIntent stopPendingIntent = PendingIntent.getBroadcast(context,
0, stopIntent, 0);
Intent startIntent = new Intent(
"com.corsalini.david.barcalc.STARTPAUSE");
PendingIntent startPendingIntent = PendingIntent.getBroadcast(context,
0, startIntent, 0);
NotificationCompat.Builder builder = new NotificationCompat.Builder(
context)
.setContentText(context.getString(R.string.notif_text))
.setContentTitle(title)
.setSmallIcon(R.drawable.ic_action_alarm_2)
.setAutoCancel(false)
.setOngoing(running)
.setOnlyAlertOnce(true)
.setContentIntent(
PendingIntent.getActivity(context, 10, new Intent(
context, FrontActivity.class)
.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP), 0))
.addAction(
running ? R.drawable.ic_action_pause
: R.drawable.ic_action_play,
running ? context.getString(R.string.pause) : context
.getString(R.string.start), startPendingIntent)
.addAction(R.drawable.ic_action_stop,
context.getString(R.string.stop), stopPendingIntent);
notificationManager.notify(id, builder.build());
}
}
Problem
Every second the notification is deleted and recreated, visually it means that every second the notification disappears and reappears in the notification list.
What I would want is to just update the TITLE text, not recreating the notification entirely every second. Is it possible?
Be sure to use the same NotificationCompat.Builder builder each time for creating the Notification!
Although the first time you have to set everything, the second time using the Builder you only have to set the value(s) you want to update. After that it's calling notificationManager.notify(id, builder.build()) just like you did. If you use the same ID then the notification gets updated (important!).
Example:
//First time
NotificationCompat.Builder builder = new NotificationCompat.Builder(context)
.setContentText(context.getString(R.string.notif_text))
.setContentTitle(title)
.setSmallIcon(R.drawable.ic_action_alarm_2)
.setAutoCancel(false)
.setOngoing(running)
.setOnlyAlertOnce(true)
.setContentIntent(
PendingIntent.getActivity(context, 10,
new Intent(context, FrontActivity.class)
.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP),
0)
)
.addAction(running ? R.drawable.ic_action_pause
: R.drawable.ic_action_play,
running ? context.getString(R.string.pause)
: context.getString(R.string.start),
startPendingIntent)
.addAction(R.drawable.ic_action_stop, context.getString(R.string.stop),
stopPendingIntent);
notificationManager.notify(id, builder.build());
//Second time
builder.setContentTitle(title);
notificationManager.notify(id, builder.build());
But you can also use the setUsesChronometer method of the NotificationCompat class. This automatically displays a chronometer using the given timestamp (able to set with setWhen).
You need to mark the notification as "only Arert Once"
Builder#setOnlyAlertOnce(true)
Thanks for the idea PieterAelse!
In my case I had to go with this (build a new notification) for the second and following times:
builder.setContentText(getConvertedTime(millisUntilFinished));
Notification notification = builder.getNotification();
notification.flags = Notification.FLAG_ONGOING_EVENT;
nm.notify(R.string.app_name,notification);
Hope it helps.
Related
I have currently setup a small application which sets an alarm on the device and stores relevant information inside of an SQL database e.g. Alarm name and time. When the alarm is activated my application sends a notification to the user. Currently each notification is static which means every message is the same. I would like to now allow my application to grab the name of the alarm which has been activated and display it in the notification. Now I know that when setting multiple alarms you require multiple ID's which I have stored in side of my SQL and I'm guess the same when it comes to sending a notification. Is there a way of matching my Alarms ID with one on a notification so that it knows what message to send e.g. alarm name?
Current code for setting my Alarm
pendingIntent = PendingIntent.getBroadcast(view.getContext(), Integer.valueOf(alarm_request_code), receiver, PendingIntent.FLAG_UPDATE_CURRENT);
alarmManager.set(AlarmManager.RTC_WAKEUP, myCalendar.getTimeInMillis(), pendingIntent);
intentArrayList.add(pendingIntent);
My Broadcast receiver...
NotificationManager notificationManager = (NotificationManager) context.getSystemService(context.NOTIFICATION_SERVICE);
Intent moveActivity = new Intent(context, AlarmActivity.class);
moveActivity.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
PendingIntent pendingIntent = PendingIntent.getActivity(context, 0, moveActivity, PendingIntent.FLAG_UPDATE_CURRENT);
NotificationCompat.Builder builder = new NotificationCompat.Builder(context)
.setContentIntent(pendingIntent)
.setContentTitle("Standard text")
.setContentText("Standard text")
.setSmallIcon(R.mipmap.ic_launcher)
.setAutoCancel(true);
notificationManager.notify(0, builder.build());
}
//////////////
Update on my situation which is slowly driving me crazy
I can now set the text from my SQL to my notification but its only the first from my database each time. Now I've come up with two possible solutions which are only theory's.
Is there a way in which each time the database is called to the notification it will move onto the next result?
As I mentioned above I'm setting an alarm and when the alarm goes off it then calls the notification. Now In my pending intent for the alarm I'm giving it a id which you can see as alarm_request_code is there a way of giving it to my notification ID and then setting up a statement where if the notification ID is equal to or in the list of my alarm ID's stored on my SQL then it will search for the correct text to input.
MyDatabaseHandler myDatabaseHandler = new MyDatabaseHandler(context, null, null, 1);
Cursor cursor = myDatabaseHandler.getAllProducts();
// Information we are trying to acquire but can only get first result
String name = cursor.getString(cursor.getColumnIndexOrThrow("alarm_name"));
String date = cursor.getString(cursor.getColumnIndexOrThrow("alarm_date"));
// Alarm ID FROM SQL which we want to match with the NOTIFICATION ID.....
String alarm_request_code = cursor.getString(cursor.getColumnIndexOrThrow("alarm_code"));
////
Log.i("The reciever is working", "perfect");
//create an intent to service
Intent service_Intent = new Intent(context, MessageService.class);
context.startService(service_Intent);
//Notification
NotificationManager notificationManager = (NotificationManager) context.getSystemService(context.NOTIFICATION_SERVICE);
Intent moveActivity = new Intent(context, AlarmActivity.class);
moveActivity.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
// Works with moveActivity to move the user back to main application.
PendingIntent pendingIntent = PendingIntent.getActivity(context, 0, moveActivity, PendingIntent.FLAG_UPDATE_CURRENT);
NotificationCompat.Builder builder = new NotificationCompat.Builder(context)
.setContentIntent(pendingIntent)
.setContentTitle(name)
.setContentText(date)
.setSmallIcon(R.mipmap.ic_launcher)
.setAutoCancel(true);
notificationManager.notify(Integer.valueOf(alarm_request_code), builder.build());
}
}
To update text store mBuilder variable
and update later in this way:
mBuilder.setContentTitle(head);
mBuilder.setContentText(body);
mNotificationManager.notify(SIMPLE_ID, mBuilder.build());
EDIT
private void simple() {
Intent intent = new Intent(context, AlarmActivity.class);
PendingIntent pIntent = PendingIntent.getActivity(this, 0, intent, 0);
mBuilder = new NotificationCompat.Builder(this);
mBuilder.setContentTitle(getResources().getString(R.string.app_name))
.setContentText(getResources().getString(R.string.app_name))
.setContentIntent(pIntent);
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP) {
mBuilder.setSmallIcon(R.drawable.ic_done_24dp);
} else {
mBuilder.setSmallIcon(someiconLollipop);
mBuilder.setColor(somecolorLollipop]);
}
noti = mBuilder.build();
//use flags if you need:
noti.flags = Notification.FLAG_ONGOING_EVENT | Notification.FLAG_NO_CLEAR;
mNotificationManager.notify(SIMPLE_ID, mBuilder.build());
}
to update the text:
private void showText() {
String head = yournewhead;
String body = yournewbody;
mBuilder.setContentTitle(head);
mBuilder.setContentText(body);
mNotificationManager.notify(SIMPLE_ID, mBuilder.build());
}
Per the docs you can do the following:
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());
The trick here is your notify id, which must be the same in order to behave appropriately, in your case 0.
So as long it has not been dismissed it should work accordingly. I will suggest having a unique id as a constant for your custom notification such as 123.
notificationManager.notify(0, builder.build());
I am using the following code for displaying notification . Upon displaying the notification , I go to the activity if I click in the notifications .
void Notify(String notificationTitle, String notificationMessage){
NotificationManager notificationManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
Notification notification = new Notification(R.drawable.noti, notificationTitle,System.currentTimeMillis());
Intent notificationIntent = new Intent(this, SmsActivity.class);
notificationIntent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP
| Intent.FLAG_ACTIVITY_SINGLE_TOP);
PendingIntent intent = PendingIntent.getActivity(this, 0,
notificationIntent, 0);
notification.setLatestEventInfo(this, notificationTitle,notificationMessage, intent);
notification.flags |= Notification.FLAG_AUTO_CANCEL;
notificationManager.notify(0, notification);
}
Now I want to update the text of notifications . How can I do that ?
You can try this
//First time
NotificationCompat.Builder builder = new NotificationCompat.Builder(context)
.setContentText(context.getString(R.string.notif_text))
.setContentTitle(title)
.setSmallIcon(R.drawable.ic_action_alarm_2)
.setAutoCancel(false)
.setOngoing(running)
.setOnlyAlertOnce(true)
.setContentIntent(
PendingIntent.getActivity(context, 10,
new Intent(context, YourActivity.class)
.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP),
0)
)
notificationManager.notify(id, builder.build());
//Second time
builder.setContentTitle(title);
notificationManager.notify(id, builder.build());
Send notification with same id:
https://developer.android.com/training/notify-user/managing.html
You can update the text of notification by sending different text in Notify(String notificationTitle, String notificationMessage) method.
The problem in approach suggested here is that if user already responded to this notification he could see it again, so you'd better to show it once instead.
So I wouldn't recommend to use this API at all in order to update your notifications.
If you are using it for that purpose you probably just exchange one bug for another.
Instead of passing 0 as notification ID, send some other number and trigger another notification with the same ID.
The existing one will be updated.
As Richard said in this question > Possible to continuously update text in the notification area? , I have the same issue here .
I want to update text in the notification area .
This question is answered and accepted , but the answer doesn't help me .
It's about to create text as bitmap dynamically and set it to Small Icon of notification .
But as Richard commented , the images for setSmallIcon must be predefined in the package.There is no ability to edit them on the fly.
Please kindly show me the right way to do this stuff .
It's quite simple to update your Notification.
First of all when you create it you must create it with an id.
NotificationManager 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("Title")
.setContentText("Text")
.setSmallIcon(R.drawable.ic_notify);
mNotificationManager.notify(
notifyID,
mNotifyBuilder.build());
Now to update your Notification you only need to notify the new notification with the old id and this will be updated (you don't need to reset the paraneter you don't want to update).
mNotifyBuilder.setContentText(setContentText("New Text")
mNotifyBuilder.setSmallIcon(R.drawable.ic_new_notify);
//this update your notification
mNotificationManager.notify(
notifyID,
mNotifyBuilder.build());
I tried to make one but it has one disadvantage is that, it has one empty notification in notification drawer,
public static int when = 0;
private void generateNotification(Context context) {
Log.i(TAG, "generateNotification");
Intent notificationIntent = new Intent(context, MainActivity.class);
PendingIntent pIntent = PendingIntent.getActivity(
this.getApplicationContext(), 0, notificationIntent,
PendingIntent.FLAG_UPDATE_CURRENT);
NotificationCompat.Builder mNotification = new NotificationCompat.Builder(
this)
// .setContentTitle("AppName")
// .setContentText("Message For Notification Drawer")
// .setSound(soundUri)
// .setDefaults(Notification.DEFAULT_SOUND)
// .setVibrate(new long[] { 1000, 1000 })
// .addAction(R.drawable.ic_launcher, "View", pIntent)
// .addAction(0, "Remind", pIntent)
// .setNumber(fCount)
// .setWhen(when)
.setSmallIcon(R.drawable.ic_launcher)
.setTicker(Integer.toString(when)) // Set String you want
.setAutoCancel(true)
.setContentIntent(pIntent);
NotificationManager notificationManager = (NotificationManager) getSystemService(NOTIFICATION_SERVICE);
// notificationManager.notify(when, mNotification.build());
notificationManager.notify(1, mNotification.build());
when++;
}
i found many answer to this, but none help :(
I have this code:
private static void generateNotification(Context context, String message) {
int icon = R.drawable.icon;
NotificationManager mNotificationManager = (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE);
int notifyID = 96;
NotificationCompat.Builder mNotifyBuilder = new NotificationCompat.Builder(context)
.setContentTitle("MyApp")
.setContentText(message)
.setDefaults(Notification.DEFAULT_ALL)
.setAutoCancel(true)
.setSmallIcon(icon);
Notification notification = mNotifyBuilder.build();
notification.flags |= Notification.FLAG_AUTO_CANCEL;
mNotificationManager.notify(notifyID, notification);
}
But if i click on notification nothing happen and it is still there. In documentation is, that i need to use:
.setAutoCancel(true)
Some one have similar problem and somebody tells him to use:
notification.flags |= Notification.FLAG_AUTO_CANCEL;
I use both, but no result :(
Thank you very much for answers. :)
I think that if you don't use an Intent with your notification, the only way to dismiss its to swipe it.
Otherwise you can use an Intent to open your activity and that will actually clear the notification:
Intent showIntent = new Intent(this, YourActivity.class);
PendingIntent contentIntent = PendingIntent.getActivity(this, 0, showIntent, 0);
And to add it to the notification:
NotificationCompat.Builder mNotifyBuilder = new NotificationCompat.Builder(context)
.setContentTitle("MyApp")
.setContentText(message)
.setDefaults(Notification.DEFAULT_ALL)
.setAutoCancel(true)
.setContentIntent(contentIntent)
.setSmallIcon(icon);
Hope this helps!
The user can dismiss all notification or if you set your notification to auto-cancel it is also removed once the user selects it.
You can also call the cancel() for a specific notification ID on the NotificationManager. The cancelAll() method call removes all of the notifications you previously issued.
Example:
mNotificationManager.cancel(notifyId);
just use this line inside button onclick event-
mNotificationManager.cancel(notifyId);//id is that u used for notification
just add
Intent showIntent = new Intent();
PendingIntent contentIntent = PendingIntent.getActivity(this, 0, showIntent, 0);
myNotification = new Notification.Builder(getApplicationContext())
.setContentTitle("Title")
.setContentText("Text")
.setTicker("notificatio")
.setContentIntent(contentIntent)
.setDefaults(Notification.DEFAULT_ALL)
.setAutoCancel(true)
.setSmallIcon(R.drawable.ic_launcher)
.build();
add empty pending intent then on click on notification, notification will remove. it works for me.
I generally use:
mNotificationManager.cancelAll();
I have tested the new BigTextStyle Notification which display correctly. However when I add action to the notification, it never get cancel and the pull-down notification area is never close when click on the action. What did I do wrong?
Drawable d = getResources().getDrawable(android.R.drawable.ic_menu_add);
Bitmap b = ((BitmapDrawable)d).getBitmap();
Notification noti = null;
Intent notificationIntent = new Intent(MainActivity.this, MainActivity.class);
String s = "Name: John \n"
+ "Surname: Doe\n"
+ "Vehicle: Honda Jazz TA-1234\n"
+ "Note: Good drifter";
Builder builder = new Notification.Builder(MainActivity.this)
.setContentTitle("New challenger arrived!")
.setContentText(s)
.setSmallIcon(R.drawable.ic_launcher)
.setLargeIcon(b)
.setTicker("New challenger arrived!")
.setPriority(Notification.PRIORITY_HIGH)
.setAutoCancel(true)
.setDefaults(Notification.DEFAULT_ALL)
.setNumber(5)
.addAction(
android.R.drawable.ic_menu_add,
"Accept",
PendingIntent.getActivity(getApplicationContext(), 0,
notificationIntent, 0, null))
.addAction(
android.R.drawable.ic_menu_delete,
"Refuse",
PendingIntent.getActivity(getApplicationContext(), 0,
notificationIntent, 0, null))
.addAction(
android.R.drawable.ic_dialog_map,
"Map",
PendingIntent.getActivity(getApplicationContext(), 0,
notificationIntent, PendingIntent.FLAG_UPDATE_CURRENT, null));
noti = new Notification.BigTextStyle(builder)
.setBigContentTitle("New challenger arrived!")
.bigText(s)
.setSummaryText("You will never win against me").build();
NotificationManager nm = (NotificationManager) MainActivity.this
.getSystemService(Context.NOTIFICATION_SERVICE);
nm.notify(0, noti);
I think you have to manually cancel the notifications if you take an action. This can be done by calling
notifMgr.cancel(0);
Clicking the notification itself should dismiss it, but for some reason actions don't seem to. The reason you pass 0 as the argument is becasue that's the ID you gave when you called:
notifMgr.notify(0, noti);
That's my updated answer, however, I had previously answered this:
It looks like you're trying to launch the same activity (from your PendingIntent) that you currently have displayed (I'm assuming this is a 1-activity app, with MainActivity containing the code above). Create another activity, build your PendingIntent so it launches that activity, then it should do as you wish. Alternatively, run your activity, notification appears, navigate to homescreen, or different app, then act on your Activity, your desired behavior should manifest.