I am currently developing an app which is using AlarmManager to start an intent to show to the user every x minutes. I would also like a persistent notification in the status bar that shows the time until the next popup. Is there a way to show a persistent notification without a background service. If not does it make sense to stop using the AlarmManager and just use the service to popup the intent every x minutes?
Essentially I need to ensure that an intent will be launched every x minutes even if the phone gets low on mem and that the notification remains in the status bar. I would also like to be able to click on the notification to reset the timer that is counting down. What is the best way to achieve these objectives?
Thanks,
Nathan
To generate Notification try this :
private void generateNotification(Context context, String message) {
int icon = R.drawable.ic_launcher;
long when = System.currentTimeMillis();
String appname = context.getResources().getString(R.string.app_name);
NotificationManager notificationManager = (NotificationManager) context
.getSystemService(Context.NOTIFICATION_SERVICE);
int currentapiVersion = android.os.Build.VERSION.SDK_INT;
Notification notification;
PendingIntent contentIntent = PendingIntent.getActivity(context, 0,
new Intent(context, myactivity.class), 0);
// To support 2.3 os, we use "Notification" class and 3.0+ os will use
// "NotificationCompat.Builder" class.
if (currentapiVersion < android.os.Build.VERSION_CODES.HONEYCOMB) {
notification = new Notification(icon, message, 0);
notification.setLatestEventInfo(context, appname, message,
contentIntent);
notification.flags = Notification.FLAG_AUTO_CANCEL;
notificationManager.notify(0, notification);
} else {
NotificationCompat.Builder builder = new NotificationCompat.Builder(
context);
notification = builder.setContentIntent(contentIntent)
.setSmallIcon(icon).setTicker(appname).setWhen(0)
.setAutoCancel(true).setContentTitle(appname)
.setContentText(message).build();
notificationManager.notify(0 , notification);
}
}
Hope this helps.
Related
On lollipop, If the user has a pin set then some notifications aren't able to be swiped away. they act like a persistent notification when attempting to be dismissed.
Some apps notifications are able to be swiped away on the lockscreen without unlocking.
I have only tested this with hide sensitive notification content, does a flag set change this ability?
How do I achieve this?
This flag makes your notification stick:
Notification.FLAG_ONGOING_EVENT;
If you leave it out you can remove it. If you put it in, it sticks.
FYI: How I make my notifications:
//These are parameters for setting up the tag in the tray
private static final String NOTIFICATION_ID_TAG="notificationID";
private static final int NOTIFICATION_ID=123456;
public void createNotification() {
// Prepare intent which is triggered if the
// notification is selected
Intent intent = new Intent(this, MainActivity_Host.class);
intent.putExtra(NOTIFICATION_ID_TAG, NOTIFICATION_ID);
PendingIntent pIntent = PendingIntent.getActivity(this, 0, intent, 0);
// Build notification
Notification noti = new Notification.Builder(this)
.setContentTitle("Service Running")
.setContentText("The service is running").setSmallIcon(R.mipmap.ic_launcher)
.setContentIntent(pIntent)
.build();
NotificationManager notificationManager = (NotificationManager) getSystemService(NOTIFICATION_SERVICE);
//THIS FLAG MAKES THE NOTIFICATION STICK = YOU CAN'T SWIPE IT AWAY... IF YOU LEAVE IT OUT YOU CAN REMOVE THE NOTIFICATION
noti.flags |= Notification.FLAG_ONGOING_EVENT;
notificationManager.notify(NOTIFICATION_ID, noti);
}
This is how you can remove the notification from within the code:
//Erase the notification that we set up when the service started
NotificationManager notificationManager = (NotificationManager)getSystemService(Context.NOTIFICATION_SERVICE);
notificationManager.cancel(NOTIFICATION_ID);
As you see, you can get the notification from the NotificationManager by the NOTIFICATION_ID you used to make it. This is just a number i made up.
My app generates notifications like so :
final Bundle intentExtras = intent.getExtras();
final String title = intentExtras.getString(Constants.EXTRA_TITLE);
final String body = intentExtras.getString(Constants.EXTRA_BODY);
final Integer notifID = intentExtras.getInt(Constants.EXTRA_ID);
// this pending intent will launch after notification is selected
Intent notificationIntent = new Intent(context, NotificationReceiverActivity.class);
notificationIntent.putExtras(intentExtras);// pass the extra data forward to NotificationReceiverActivity
notificationIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
PendingIntent pendingIntent = PendingIntent.getActivity(context, notifID, notificationIntent, PendingIntent.FLAG_ONE_SHOT);
// build notification to show on the notification bar
try
{
final String packagename = context.getPackageName();
PackageInfo packageinfo = context.getApplicationContext().getPackageManager().getPackageInfo(packagename, 0);
final int iconid = packageinfo.applicationInfo.icon;
NotificationCompat.Builder mBuilder = new NotificationCompat.Builder(context)
.setAutoCancel(false)
.setContentIntent(pendingIntent)
.setSmallIcon(iconid)
.setContentTitle(title)
.setContentText(body);
// build notification and set alerts
Notification notification = mBuilder.build();
notification.defaults |= Notification.DEFAULT_ALL;
// show notification
NotificationManager notificationMgr = (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE);
notificationMgr.notify(notifID, notification);
}
catch (android.content.pm.PackageManager.NameNotFoundException e)
{}
each notifID is unique ! However, if the app is showing two or more notifications, and the user selects one of them, both notifications for the app are cleared !
I have tried using setAutoCancel(false) or setAutoCancel(true) but it doesn't make a difference.
Additionally, there are no calls to NotificationManager.cancel() or NotificationManager.cancelAll()
How can I prevent the app from clearing all notifications for the app after a user has selected just one of them ?
FURTHER INVESTIGATION...
I've found that the notifications for the app disappear after I launch the app.
However, no .cancel() or .cancelAll() in sight... /confused
Answer: Crosswalk (XWalkView) took the liberty of .cancelAll() notifications !!!
/facepalm x 100000
https://github.com/wuhengzhi/crosswalk/commit/32205e256dbb35ee70c895de4fe7c76d165b30dd
I try to make my notification(from Service) updating or refreshing in every five minutes. How can I do this? This is, what i want to update.
if (...){
int icon = R.drawable.updatedImage1;
long when = System.currentTimeMillis();
NotificationManager notificationManager = (NotificationManager) this
.getSystemService(Context.NOTIFICATION_SERVICE);
CharSequence message = "II Tydzień";
Notification notification = new Notification(icon, message, when );
String title = this.getString(R.string.app_name); // Here you can pass the value of your TextView
Intent notificationIntent = new Intent(this, MainActivity.class);
notificationIntent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP );
PendingIntent intent = PendingIntent.getActivity(this, 0, notificationIntent, 0);
notification.setLatestEventInfo(this, title, message, intent);
notification.flags |= Notification.FLAG_NO_CLEAR;
notificationManager.notify(0, notification);
} else { ...other notification }
Condition is period of time, so I need to change notification depending on what time is it.
You can use AlarmManager to schedule your notification repeatedly at different time intervals. The docs mention that:
This class provides access to the system alarm services. These allow you to schedule your application to be run at some point in the future. When an alarm goes off, the Intent that had been registered for it is broadcast by the system, automatically starting the target application if it is not already running
You might be able to use setRepeating function for your purpose.
I am developing an Android app and I want a status bar notification that cannot be cleared by the user. Does anyone know how to do that? I've seen them with apps like Skimble where a non-clearable notification appears while using the application.
Also, I'd when the user clicks/presses the notification, I want it to return to the app instance that is already running. Right now it starts a new instance. Again like the Skimble app, I just want to return to the already running instance of the app.
Thanks.
I found a solution to this problem. I used FLAG_ONGOING_EVENT to make the notification persist. Here's the code:
String ns = Context.NOTIFICATION_SERVICE;
NotificationManager mNotificationManager = (NotificationManager) getSystemService(ns);
int icon = R.drawable.mypic;
long when = System.currentTimeMillis();
Notification notification = new Notification(icon, tickerText, when);
notification.flags = Notification.FLAG_ONGOING_EVENT;
Context context = getApplicationContext();
CharSequence contentTitle = "Title Text";
CharSequence contentText = "Content text.";
Intent intent = new Intent(this, MyClass.class);
intent.setAction("android.intent.action.MAIN");
intent.addCategory("android.intent.category.LAUNCHER");
PendingIntent contentIntent = PendingIntent.getActivity(this, 0, intent, 0);
notification.setLatestEventInfo(context, contentTitle, contentText, contentIntent);
final int HELLO_ID = 1;
mNotificationManager.notify(HELLO_ID, notification);
Here is the solution for the NotificationCompat.Builder
NotificationCompat.Builder builder = new NotificationCompat.Builder(this)
.setSmallIcon(R.drawable.ic_launcher)
.setContentTitle("MyApp")
.setContentText("MyMsg")
.setOngoing(true);
More at the Google docs.
notification.setLatestEventInfo is deprecated so you have to use the Notification.builder and if your using 2.X and lower API you have to use NotificationComacpt.Builder and this is not applicable and I couldn't make my notification stays. so I used setDeleteIntent and pointed to the same activity and on resume method just call the block of code which shows your notification. So it is kinda work around.
from my service I send (with "ongoing" ID = 0) ongoing notification and it seems that there is no way of clearing it from code. if I send other notifications to the same ID (0), icon and intents
will update :/
I dont know if this is a bug in API 7 but it just dont make sens to me.
when I sent notification with Notification.FLAG_ONLY_ALERT_ONCE with different ID(ex. 1) then it is classified as simple notification and I could easily clear it from expanded menu or from code. BUT just by sending same notification to previous ID (0) it is classified as ongoing and I cannot cancel it anyhow!
I also tried to save reference to "ongoing" notification and then re-notify it with other PendingIntent and/or flags but it has no effect!
my current code of the service
#Override
public int onStartCommand(Intent intent, int flags, int startId)
{
Log.d(TAG, "start notification");
startStatusBarNotification();
//do other stuff
// We want this service to continue running until it is explicitly stopped, so return sticky.
return START_STICKY;
}
private void startStatusBarNotification()
{
Log.d(TAG, "startStatusBarNotification.");
final int icon = R.drawable.stbar_icon_fail;
final long when = System.currentTimeMillis();
final Notification notification = new Notification(icon, getString(R.string.notify_title), when);
final Intent notificationIntent = new Intent(this, MyActivity.class);
notificationIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
final PendingIntent contentIntent = PendingIntent.getActivity(this, 0, notificationIntent, PendingIntent.FLAG_CANCEL_CURRENT);
notification.setLatestEventInfo(this, getString(R.string.notify_title), expandText, contentIntent);
notification.flags = Notification.FLAG_ONGOING_EVENT | Notification.FLAG_FOREGROUND_SERVICE;//| Notification.FLAG_NO_CLEAR
Log.d(TAG, "notify send.");
final NotificationManager mNotificationManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
mNotificationManager.notify(SERVICE_ONGOING_NOTIFICATION_ID, notification);//ID = 0
}
#Override
public void onDestroy()
{
Log.d(TAG, "clear status bar notification.");
cancelNotification();
super.onDestroy();
}
private void cancelNotification()
{
final int icon = R.drawable.stbar_icon_exit;
final long when = System.currentTimeMillis();
final Notification notification = new Notification(icon, getString(R.string.notify_title), when);
final PendingIntent contentIntent = PendingIntent.getActivity(this, 0, null, PendingIntent.FLAG_CANCEL_CURRENT);
notification.setLatestEventInfo(this, getString(R.string.notify_stopping_title), getString(R.string.notify_stopping_text), contentIntent);
notification.flags = Notification.FLAG_AUTO_CANCEL;
final NotificationManager mNotificationManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
mNotificationManager.cancel(SERVICE_ONGOING_NOTIFICATION_ID); //NOTHING HAPPENS
mNotificationManager.notify(SERVICE_ONGOING_NOTIFICATION_ID, notification); //ID = 0 but if this was changed to 1 cancel notification can be cleared :/
}
I can see "exit" icon so onDestroy and cancelNotification are called, i have no idea what im doing wrong
It does not appear that you can successfully cancel ongoing notifications with ID 0: you will probably have to use a non-zero notification id.
The core notification manager service code is here, which doesn't appear to have a specific restriction on the choice of notification ID but everyone else who uses ONGOING notifications (for example, the Phone application) uses non-zero IDs.