I'm trying to create a notification for my app that has an action that I can change its icon, title and intent when I click on it.
I see its possible here at 3:33
https://www.youtube.com/watch?v=tKoQatxG0_8&index=73&list=PLOU2XLYxmsIIwGK7v7jg3gQvIAWJzdat_
But I couldn't find a way to do it.
also, If someone know how to use the pause/play icon on the Right watch in the link, i'll like to know that also.
Thanks from advance.
You can access notification actions from notificationObj.actions
Try below: (Note: below code is not complete, but it will give you an idea on how to change action icon)
Notification status = null;
private NotificationCompat.Builder mBuilder;
private NotificationManager mManager;
private final int STATUS_ID = 1;
private String CHANNEL_ID = "channel_name";
private void setUpNotification() {
mManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
int playOrPause;
if(isPlaying()) {
playOrPause = R.drawable.ic_pause;
} else {
playOrPause = R.drawable.ic_play;
}
if(mBuilder == null) {
//Setup Builder
mBuilder = new NotificationCompat.Builder(this, CHANNEL_ID);
mBuilder.setOngoing(true)
.addAction(playOrPause, "play", pendingIntent1) // Index 0
.addAction(R.drawable.ic_2, "text2", pendingIntent2) // Index 1
.addAction(R.drawable.ic_3, "text3", pendingIntent3);// Index 2
status = mBuilder.build();
} else {
//Update builder as per your needs
mBuilder.setContentTitle(title);
status = mBuilder.build();
status.actions[0] = new Notification.Action(playOrPause, "play", pendingIntent1);
}
startForeground(STATUS_ID, status);
}
I was able to solve the same problem by accessing builder.mActions. It's an ArrayList of all the actions you've added. I modify this without recreating the builder and calling build seems to update this.
This doesn't seem to be documented in the SDK but I'm ok with that for now.
Will let you know if I come up with something else
By following #Sammer J suggestion I came up with the following solution.
try {
// mBuilder is a Notification.Builder object.
Field field = mBuilder.getClass().getDeclaredField("mActions");
field.setAccessible(true);
ArrayList<Notification.Action> mActions = (ArrayList<Notification.Action>) field.get(mBuilder);
if (mActions != null) {
mActions.set(0, new Notification.Action(R.drawable.ic_action_resume, getString(R.string.button_resume), pendingIntent));
field.set(mBuilder, mActions);
}
} catch (NoSuchFieldException | IllegalAccessException e) {
e.printStackTrace();
}
mNotificationManager.notify(ONGOING_NOTIFICATION_ID, mBuilder.build());
Related
I have a service that calls a BroadcastReceiver. It was working fine but after I changed the back-end system for handling notification ids, the final notification update which should update a notification to tell the user that a process has finished. However, that final update would not pass through unless I place a breakpoint in debugging mode in the method handling those notifications. If a breakpoint is not placed or debug mode is not active, that final notification update would not happen and the notification would display its last state which tells the user that the process has not finished, which is not the case.
Here's the method, and the Log.d()s show that the manager.notify() method was called properly to update the notification to signify that the process has finished.
#Override
public void onReceive(Context context, Intent intent) {
Download data = null;
try {
data = (Download) intent.getSerializableExtra(Commons.ARGS.DATA);
} catch (ClassCastException | NullPointerException e) {
e.printStackTrace();
}
switch (intent.getIntExtra(Commons.ARGS.RESULT, Commons.ARGS.FAILED)) {
case Commons.ARGS.DESTROY:
Log.w(TAG, "Service was destroyed");
if (notifications && manager != null) {
Download[] remaining = (Download[]) intent.getParcelableArrayExtra(Commons.ARGS.DATA);
if (remaining == null) break;
for (Download d : remaining) {
// Download has failed since service was destroyed; was never called and has no relations to this case. manager.notify() is called here to update the notification as "cancelled" btw
}
}
break;
case Commons.ARGS.ERR_LOAD:
Log.w(TAG, "Failed to load queue");
break;
}
if (data == null) return;
if (notifications) {
Intent i = new Intent(context, MainActivity.class);
NotificationCompat.Builder builder = new NotificationCompat.Builder(activity, Commons.Notif.DOWNLOAD_PROGRESS)
.setContentIntent(PendingIntent.getActivity(activity, 0, i, 0))
.setPriority(NotificationCompat.PRIORITY_HIGH)
.setSmallIcon(R.drawable.ic_notif)
.setContentTitle(data.title)
.setColor(context.getResources().getColor(R.color.Accent))
.setGroupAlertBehavior(NotificationCompat.GROUP_ALERT_SUMMARY)
.setGroup(CHANNEL_ID);
if (manager == null) {
manager = (NotificationManager) activity.getSystemService(Context.NOTIFICATION_SERVICE);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
NotificationChannel channel = new NotificationChannel(CHANNEL_ID, "Downloads in Progress", NotificationManager.IMPORTANCE_DEFAULT);
channel.setDescription("All downloads are displayed here");
channel.enableLights(false);
channel.enableVibration(false);
manager.createNotificationChannel(channel);
}
}
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
builder.setChannelId(CHANNEL_ID);
}
// Notification builder styling is handled here
manager.notify(0, new NotificationCompat.Builder(activity, Commons.Notif.DOWNLOAD_PROGRESS)
.setChannelId(CHANNEL_ID)
.setSmallIcon(R.drawable.ic_notif)
.setGroup(CHANNEL_ID)
.setColor(activity.getResources().getColor(R.color.Accent))
.setGroupAlertBehavior(NotificationCompat.GROUP_ALERT_SUMMARY)
.setGroupSummary(true)
.setContentText("All downloads have finished.")
.setContentTitle("Done")
.build());
manager.notify(DOWNLOAD_BASE_ID | (data.id & 0x00FF_FFFF), builder.build());
Log.d(TAG, "Notification updated");
}
}
Thanks in advance :P
I do not know what exactly is happening but canceling the notification using manager.cancel() before updating it with the success/final notification solved the problem.
int id = // Notification id
if (success) {
Log.d(TAG, "Success Notification updated");
manager.cancel(id);
} else Log.d(TAG, "Notification updated");
manager.notify(id, builder.build());
I am using foregroundService for playing audio in Background and show a notification with actions.
public NotificationHelper(ForegroundService service) {
mFG_Service = service;
mNotificationManager = (NotificationManager) mFG_Service.getSystemService(Context.NOTIFICATION_SERVICE);
}
public void showNotification(ChaptersBO chaptersBO, boolean isPlaying) {
Notification notification = createNotification(chaptersBO, isPlaying);
if (notification != null) {
if (isPlaying) {
mFG_Service.startForeground(NOTIFICATION_ID.FOREGROUND_SERVICE, notification);
} else {
mFG_Service.stopForeground(false);
mNotificationManager.notify(NOTIFICATION_ID.FOREGROUND_SERVICE, notification);
}
}
}
private Notification createNotification(ChaptersBO chapter, boolean isPlaying) {
if (chapter == null)
return null;
NotificationCompat.Builder builder = new NotificationCompat.Builder(mFG_Service);
try {
Bitmap sourceBitmap = BitmapFactory.decodeResource(mFG_Service.getResources(), R.drawable.notification_logo);
Bitmap resizedBitmap = Bitmap.createScaledBitmap(sourceBitmap, 300, 300, false);
if (resizedBitmap != sourceBitmap) {
sourceBitmap.recycle();
}
builder.setContentTitle("Audio")
.setContentText(chapter.getChapterNumber())
.setPriority(Notification.PRIORITY_DEFAULT)
.setSmallIcon(getSmallIcon(isPlaying))
.setLargeIcon(resizedBitmap)
.setShowWhen(false)
.setOngoing(isPlaying)
.setContentIntent(getPendingIntent())
.addAction(R.drawable.ic_notif_prev, "", getAction(ACTION.PREV_ACTION, REQ_CODE_PREVIOUS))
.addAction(getSmallIcon(isPlaying), "", getAction(ACTION.PLAY_PAUSE_ACTION, REQ_CODE_PLAY_OR_PAUSE))
.addAction(R.drawable.ic_notif_next, "", getAction(ACTION.NEXT_ACTION, REQ_CODE_NEXT))
.setDeleteIntent(getStopIntent())
.setStyle(new NotificationCompat.DecoratedCustomViewStyle());
} catch (Exception e) {
e.printStackTrace();
}
return builder.build();
}
I want to update notification small icon and center action icon on play/pause. For the first time it works fine but if I clear the notification and play another audio then these icons (Encircled in below screenshot) are not updating.
To pause audio I am calling this:
mNotificationManager.notify(NOTIFICATION_ID.FOREGROUND_SERVICE, notification);
If I replace it with this
mFG_Service.startForeground(NOTIFICATION_ID.FOREGROUND_SERVICE, notification);
then it works fine but in that case I can't clear notification.
Any suggestions to update these icons on Play/Pause and also make the notification removable when audio is paused will be appreciated.
I'm getting notification from fcm when app is in foreground or background.
I don't want to show the notification When app in a specific activity how to disable notification when app is in specific activity.
I'm using datapaylod to for notification
You can check current top activity by:
public static Activity getActivity() {
Class activityThreadClass = Class.forName("android.app.ActivityThread");
Object activityThread = activityThreadClass.getMethod("currentActivityThread").invoke(null);
Field activitiesField = activityThreadClass.getDeclaredField("mActivities");
activitiesField.setAccessible(true);
Map<Object, Object> activities = (Map<Object, Object>) activitiesField.get(activityThread);
if (activities == null)
return null;
for (Object activityRecord : activities.values()) {
Class activityRecordClass = activityRecord.getClass();
Field pausedField = activityRecordClass.getDeclaredField("paused");
pausedField.setAccessible(true);
if (!pausedField.getBoolean(activityRecord)) {
Field activityField = activityRecordClass.getDeclaredField("activity");
activityField.setAccessible(true);
Activity activity = (Activity) activityField.get(activityRecord);
return activity;
}
}
return null;
}
you can check if top activity is the activity in which you don't want to show notification and then return the call from service.
Try this,
private void sendNotification(String msg) {
Intent notificationIntent = null;
notificationIntent = new Intent(currentactivity.this, Main2Activity.class);
notificationIntent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
PendingIntent contentIntent = PendingIntent.getActivity(GCMNotificationIntentService.this, 0, notificationIntent, PendingIntent.FLAG_CANCEL_CURRENT);
NotificationManager nm = (NotificationManager) GCMNotificationIntentService.this.getSystemService(Context.NOTIFICATION_SERVICE);
Resources res = GCMNotificationIntentService.this.getResources();
NotificationCompat.Builder builder = new NotificationCompat.Builder(GCMNotificationIntentService.this);
builder.setContentIntent(contentIntent)
.setSmallIcon(R.drawable.app_logo_small_trans)
.setColor(getResources().getColor(R.color.app_logo_color))
.setLargeIcon(BitmapFactory.decodeResource(res, R.drawable.app_logo))
.setTicker(msg)
.setWhen(System.currentTimeMillis())
.setAutoCancel(true)
.setContentTitle("Propreka")
.setLights(0xffff0000, 100, 2000)
.setPriority(Notification.DEFAULT_SOUND)
.setContentText(msg);
Notification n = builder.getNotification();
n.defaults |= Notification.DEFAULT_ALL;
nm.notify(0, n);
}
So you want to know which (if any) activity is in foreground at the moment. And depending on the class type, want to limit the showing of notifications.
You need to maintain this yourself. Easiest way is to write a new class and have public static functions in it to mark activity as active / inactive
public static Activity mCurrentActivity = null;
public static void SetActivity(Activtiy activity) { mCurrentActivity = activity };
public static void ClearActivity(Activtiy activity)
{
if (mCurrentActivity.equals(activity))
mCurrentActivity = null;
}
public static Activity GetCurrentActivity() { return mCurrentActivity; }
Once you have such an infra, you can call the SetActivity and ClearActivity functions in all of your onResume and onPause overrides respectively.
Finally, in your notification builder class, you will get the instance of current activity and compare the .class to check if your desired activity is the one in focus. If the Current activity returns null, it means your app is not in foreground.
There are better, more efficient and cleaner way to do this. E.g. Dependency Injection with Daggr.
Currently I am working on GCM (Google Cloud message), it allow user to push the message to user device. And I would like achieve the following requirement :
if the user has already enter app , ignore it
if the user has not enter the app , click on notification to enter the app
And the work flow of my app is:
WelcomePage (download json and create data set from it) => MainPage (Display base on the data set)
The code to handle notification
private void sendNotification(String msg) {
mNotificationManager = (NotificationManager) this.getSystemService(Context.NOTIFICATION_SERVICE);
String notifyMsg = "";
JSONTokener tokener = new JSONTokener(msg);
if (tokener != null) {
try {
notifyMsg = new JSONObject(tokener).getString("msg");
} catch (JSONException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
Intent myintent = new Intent(this, WelcomePageActivity.class);
myintent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_ACTIVITY_SINGLE_TOP);
PendingIntent contentIntent = PendingIntent.getActivity(this, 0, myintent, PendingIntent.FLAG_UPDATE_CURRENT);
NotificationCompat.Builder mBuilder = new NotificationCompat.Builder(this)
.setSmallIcon(R.drawable.ic_launcher)
.setContentTitle(getResources().getString(R.string.notification_title))
.setStyle(new NotificationCompat.BigTextStyle()
.bigText(notifyMsg))
.setContentText(notifyMsg)
.setContentIntent(contentIntent);
mNotificationManager.notify(NOTIFICATION_ID, mBuilder.build());
}
The problem is if I use WelcomePageActivity class , it will create a new activity if I am at the main page, how can I adjust the code to fit my requirement ?
Thanks
For
1. if the user has already enter app , ignore it:
in the onReceive() , check if your app is running, do not notify.
It can be checked with something like:
ActivityManager activityManager =(ActivityManager)gpsService.this.getSystemService(ACTIVITY_SERVICE);
List<ActivityManager.RunningServiceInfo> serviceList= activityManager.getRunningServices(Integer.MAX_VALUE);
if((serviceList.size() > 0)) {
boolean found = false;
for(int i = 0; i < serviceList.size(); i++) {
RunningServiceInfo serviceInfo = serviceList.get(i);
ComponentName serviceName = serviceInfo.service;
if(serviceName.getClassName().equals("Packagename.ActivityOrServiceName")) {
//Your service or activity is running
break;
}
}
if the user has not enter the app , click on notification to enter the app
from the code above, you'l know if you would like to resume the app or launch - call Splash Screen or in your case WelcomeActivity.
About the workflow of your app, i'd suggest check whether you need to download the data every time or not. Can save it maybe or update/download only when required, and rest of flow works as it is.
In your AndroidManifest.xml, define your WelcomePageActivity with the flag android:launchMode="singleTop". From the definition of this flag:
A new instance of a "singleTop" activity may also be created to handle
a new intent. However, if the target task already has an existing
instance of the activity at the top of its stack, that instance will
receive the new intent (in an onNewIntent() call); a new instance is
not created.
So with this flag, your activity will not be created again, rather it will receive a call in the onNewIntent() function with the Intent you used to create the PendingIntent for the notification. You could override this function, and use the intent to pass the activity new information.
You will not able to receive any notification click event so,
try this code :
Intent myintent = new Intent(this, TestActivity.class);
myintent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_ACTIVITY_SINGLE_TOP);
PendingIntent contentIntent = PendingIntent.getActivity(this, 0, myintent, PendingIntent.FLAG_UPDATE_CURRENT);
NotificationCompat.Builder mBuilder = new NotificationCompat.Builder(this)
.setSmallIcon(R.drawable.ic_launcher)
.setContentTitle(getResources().getString(R.string.notification_title))
.setStyle(new NotificationCompat.BigTextStyle()
.bigText(notifyMsg))
.setContentText(notifyMsg)
.setContentIntent(contentIntent);
mNotificationManager.notify(NOTIFICATION_ID, mBuilder.build());
}
public class TestActivity extends Activity{
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
// check for your app state is running or not
if(appRunning == false) {
// start your WelcomePage activity.
}
}
}
1.Create an object in GcmIntentService
public static final Object CURRENTACTIVIYLOCK = new Object();
//for storing current activity
public static Activity currentActivity;
2.Update this object value in onPause and onResume of MainActivity to recognize Activity is running or not.
#Override
public void onResume() {
super.onResume();
System.out.println("onResume Home page");
synchronized (GcmIntentService.CURRENTACTIVIYLOCK) {
GcmIntentService.currentActivity = this;
}
}
#Override
public void onPause() {
super.onPause();
synchronized (GcmIntentService.CURRENTACTIVIYLOCK) {
GcmIntentService.currentActivity = null;
}
}
3.In GcmIntentService class, check for the current activity in onHandleIntent method.
synchronized (CURRENTACTIVIYLOCK) {
if (currentActivity != null) {
if (currentActivity.getClass() == HomePageActivity.class) {
} else {
sendNotification(extras.getString("message"));
}
} else {
sendNotification(extras.getString("message"));
}
I'm sure this will help you.
I have a Notification, which supports play,pause forward and back.
private static Notification createNotification(String interpret, String title, boolean paused) {
// if (builder == null)
builder = new NotificationCompat.Builder(context);
builder.setPriority(Notification.PRIORITY_MAX);
builder.setAutoCancel(false);
builder.setContentTitle(title);
builder.setContentText(interpret);
builder.setOngoing(true);
builder.setOnlyAlertOnce(true);
builder.setSmallIcon(R.drawable.ic_launcher);
builder.setContentIntent(PendingIntent.getActivity(context, 9, new Intent(context, ApplicationActivity.class), Intent.FLAG_ACTIVITY_BROUGHT_TO_FRONT));
builder.addAction(R.drawable.av_previous, "", PendingIntent.getBroadcast(context.getApplicationContext(), 0, new Intent(NotificationPlayerControlReceiver.MUSIC_PLAYER_INTENT).putExtra("resultcode", NotificationPlayerControlReceiver.PREVIOUS), PendingIntent.FLAG_CANCEL_CURRENT));
if (paused)
builder.addAction(R.drawable.av_play, "", PendingIntent.getBroadcast(context.getApplicationContext(), 2, new Intent(NotificationPlayerControlReceiver.MUSIC_PLAYER_INTENT).putExtra("resultcode", NotificationPlayerControlReceiver.PLAY), PendingIntent.FLAG_CANCEL_CURRENT));
else
builder.addAction(R.drawable.av_pause, "", PendingIntent.getBroadcast(context.getApplicationContext(), 3, new Intent(NotificationPlayerControlReceiver.MUSIC_PLAYER_INTENT).putExtra("resultcode", NotificationPlayerControlReceiver.PAUSE), PendingIntent.FLAG_CANCEL_CURRENT));
builder.addAction(R.drawable.av_next, "", PendingIntent.getBroadcast(context.getApplicationContext(), 1, new Intent(NotificationPlayerControlReceiver.MUSIC_PLAYER_INTENT).putExtra("resultcode", NotificationPlayerControlReceiver.NEXT), PendingIntent.FLAG_CANCEL_CURRENT));
Notification notification = builder.build();
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB)
notification.tickerView = null;
return notification;
}
Updating the notification:
public static void update(String interpret, String title, boolean paused) {
NotificationManager manager = (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE);
manager.notify(0, createNotification(interpret, title, paused));
}
To avoid blinking on update, I´ve set the builder to a global variable and I reuse it on every update, which works great. but reusing it, means that also all buttons I´ve added are reused and there is no possibility to remove Actions I´ve added before.
The button change only works, if I reinitialize the NotificationCompat.Builder on every update, which means I get the blinking again.
How do I avoid blinking, but letting the button change?
EDIT:
Just checked out Rocket Player, they didn´t solve the problem too, but Google Play Music did
Like Boris said, the problem is that a new notification will be build every update.
My solution covers the same logic, but I use the NotificationBuilder...
here is the code:
if (mNotificationBuilder == null) {
mNotificationBuilder = new NotificationCompat.Builder(this)
.setSmallIcon(iconId)
.setContentTitle(title)
.setContentText(message)
.setLargeIcon(largeIcon)
.setOngoing(true)
.setAutoCancel(false);
} else {
mNotificationBuilder.setContentTitle(title)
.setContentText(message);
}
keep in mind that mNotificationBuilder is a private field in the class.
The issue is that you create new notification every time you want to update. I had the same issue and it fixed when I did the following:
retain the instance of the notification inbetween different calls of createNotification.
set this instance to null every time it is removed from the notification bar.
do the following code:
Code:
private static Notification createNotification(String interpret, String title, boolean paused) {
if (mNotification == null) {
// do the normal stuff you do with the notification builder
} else {
// set the notification fields in the class member directly
... set other fields.
// The below method is deprecated, but is the only way I have found to set the content title and text
mNotification.setLatestEventInfo(context, contentTitle, contentText, contentIntent);
}
return mNotification;
}
And now when you call notify no blinking will appear:
manager.notify(0, createNotification(interpret, title, paused));
PS: I also faced a problem that if I executed setLatestEventInfo the large and small icons got scrwed up. That's why I did:
int tmpIconResourceIdStore = mNotification.icon;
// this is needed to make the line below not change the large icon of the notification
mNotification.icon = 0;
// The below method is deprecated, but is the only way I have found to set the content title and text
mNotification.setLatestEventInfo(context, contentTitle, contentText, contentIntent);
mNotification.icon = tmpIconResourceIdStore;
Looking into Adnroid ccode this line mNotification.icon = 0; disables the icon screw up.
I know that this is a rather old question, but since I didn't found a solution anywhere else, I thought answering this now might help others with the same problem.
This problem is kind of tricky to begin with. I encountered it today as well, and being my stubborn self, I found a solution after searching and trying for a while.
How to solve this problem:
In order to be compatible with API-Levels lower than 19, my solution is to use the NotificationCompat classes from the support-library.
As suggested by others, I keep the reference to the NotificationCompat.Builder for as long as the notification is required. The actions I use in my Notification are only added upon initial creation of the Builder, and those actions that will change depending on the situation, I also store in a private member of the service. Upon change, I re-use the Builder object and adjust the NotificationCompat.Action object according to my needs. Then I call the Builder.getNotification() or Builder.build() method, depending on API-level (probably not necessary due to the support-libs, but I didn't check that. If I can omit that, please write a comment, so I can improve my code ;)
Here's an example code of what I just described above:
public Notification createForegroundNotification(TaskProgressBean taskProgressBean, boolean indeterminate) {
Context context = RewardCalculatorApplication.getInstance();
long maxTime = TaskUtils.getMaxTime(taskEntry);
long taskElapsedTime = TaskUtils.calculateActualElapsedTime(taskProgressBean);
long pauseElapsedTime = taskProgressBean.getPauseElapsedTime();
int pauseToggleActionIcon;
int pauseToggleActionText;
PendingIntent pauseToggleActionPI;
boolean pauseButton = pauseElapsedTime == 0;
if(pauseButton) {
pauseToggleActionIcon = R.drawable.ic_stat_av_pause;
pauseToggleActionText = R.string.btnTaskPause;
pauseToggleActionPI = getPendingIntentServicePause(context);
} else {
pauseToggleActionIcon = R.drawable.ic_stat_av_play_arrow;
pauseToggleActionText = R.string.btnTaskContinue;
pauseToggleActionPI = getPendingIntentServiceUnpause(context);
}
String contentText = context.getString(R.string.taskForegroundNotificationText,
TaskUtils.formatTimeForDisplay(taskElapsedTime),
TaskUtils.formatTimeForDisplay(pauseElapsedTime),
TaskUtils.formatTimeForDisplay(taskProgressBean.getPauseTotal()));
// check if we have a builder or not...
boolean createNotification = foregroundNotificationBuilder == null;
if(createNotification) { // create one
foregroundNotificationBuilder = new NotificationCompat.Builder(context);
// set the data that never changes...plus the pauseAction, because we don't change the
// pauseAction-object, only it's data...
pauseAction = new NotificationCompat.Action(pauseToggleActionIcon, getString(pauseToggleActionText), pauseToggleActionPI);
foregroundNotificationBuilder
.setContentTitle(taskEntry.getName())
.setSmallIcon(R.drawable.ic_launcher)
.setContentIntent(getPendingIntentActivity(context))
.setOngoing(true)
.addAction(R.drawable.ic_stat_action_done, getString(R.string.btnTaskFinish), getPendingIntentServiceFinish(context))
.addAction(pauseAction);
}
// this changes with every update
foregroundNotificationBuilder.setContentText(contentText);
if(indeterminate) {
foregroundNotificationBuilder.setProgress(0, 0, true);
} else {
foregroundNotificationBuilder.setProgress((int) maxTime, (int) taskElapsedTime, false);
}
// if this is not the creation but the button has changed, change the pauseAction's data...
if(!createNotification && (pauseButton != foregroundNotificationPauseButton)) {
foregroundNotificationPauseButton = pauseButton;
pauseAction.icon = pauseToggleActionIcon;
pauseAction.title = getString(pauseToggleActionText);
pauseAction.actionIntent = pauseToggleActionPI;
}
return (Build.VERSION.SDK_INT < Build.VERSION_CODES.JELLY_BEAN)
? foregroundNotificationBuilder.getNotification() // before jelly bean...
: foregroundNotificationBuilder.build(); // since jelly bean...
}
The variables foregroundNotificationBuilder, pauseAction and foregroundNotificationPauseButton are private members of the service class.
The getPendingIntent...() methods are convenience methods that simply create the PendingIntent objects.
This method is then called when I need to update the notification using the NotificationManager, as well as handed over to the service's startForeground() method. This solves the flickering and the problems with the not updatable actions in the notification.