How do i remove a foreground notification in Android Lollipop? - android

I'm looking to stop/dismiss a foreground notification for a service for a mediaplayer, much similar to Google's implementation for Google Music.
For instance in Google Music, if you are playing music then the the notification cannot be swiped away. However if you pause the music it can.
This is completely different to how it is implemented on Android 4.4, where the notification starts only when you leave the app and removes itself when you go back into the app. I can't see how to implement this either considering the requirements for a service to have a notification.
Any help would be much appreciated.

How do i remove a foreground notification in Android Lollipop?
You can remove your own foreground Notification by calling stopForeground() from your Service, that called startForeground().
For instance in Google Music, if you are playing music then the the notification cannot be swiped away. However if you pause the music, you can swipe it away.
Presumably, they are updating the setOngoing() value for the Notification based upon whether or not the music is playing.

You can also remove the notification in a tricky way:
start 1st service with startForeground(1, new Notification());
start 2nd service with startForeground(1, new Notification()); and immediately stop it
As a result 1st service is still running in foreground but the notification is gone thanks to stopping 2nd service. I've found it by accident :).

Related

Silent notifications in foreground services

I have multiple apps that kind of work together to do the same job and they all belong to the same developer. Each app runs a long-running service in the background and keeps processing user's input. The problem is that those services cannot run in the background for a long time because Android system will kill them. So I want to use foreground services instead of background ones to prevent the system from killing them. However, I don't want to annoy the users with multiple different notifications in the notification drawer.
I found out that creating a notification without assigning a channel in Android O, will let the system start the foreground service without showing a notification. Something like the following:
Notification.Builder builder = new Notification.Builder(context);
builder.setContentTitle(......);
builder.setTicker(......);
builder.setContentText(......);
builder.setSmallIcon(......);
builder.setLargeIcon(......);
Notification notification = builder.build();
startForeground(111, notification);
So I was thinking of showing a notification by creating a notification with a channel from one app and create a notification without a channel for the other apps as I described earlier. In that case, the user will see one notification for all my apps.
That solution works well for me. But I am wondering if it is an unintended use of the notification in the foreground services. I am afraid that Google will suspend my apps for doing that!!
Do you guys know if it is okay to implement that solution?
Or is there any way to stack the notifications together in a group even though they are different apps?
My goal is just to make the notification less annoying to the user.
Also, I am aware of JobScheduler & JobIntentService solutions. But they don't do the job in my case because I want to keep the service running. Not like do one job and stop the service...
You can create notification channel with IMPORTANCE_LOW (https://developer.android.com/training/notify-user/channels#importance).
There shouldn't be sound.
Or you can also use setOnlyAlertOnce() (https://developer.android.com/training/notify-user/build-notification#Updating) and the sound will be only once.

Best way to create a service that doesn't die.(like WhatsApp or Facebook)

I have tried till now
- start sticky
- alarm to restart service
- on task removed start the service
- use job service (has latency and executes task slow)
Is there a proper method to make an infallible background service like the popular apps?
Creating a background service that "does not die" is not possible in android.
You can create a service and take certain measures to have it running as much as possible, but the OS will kill it at times and your service will not be running until the OS decides to restart it (in case it is a sticky service).
Things you can do:
Make the service sticky, so that it will be restarted by the OS after the OS kills it. It is impossible to predict when it will be restarted. It can be almost instant, it can take seconds, minutes, hours, or more.
Start the service when you open the app.
Start the service when the app is upgraded, using the MY_PACKAGE_REPLACED broadcast.
Start the service when the device is (re)booted, using the BOOT_COMPLETED and REBOOT broadcasts.
Override onTaskRemoved in the service, to schedule a restart of the service in case the user swipes away your app from the list of recent apps.
Use FCM to periodically send messages to the app with an instruction to start the service in case it is not running anymore.
You can never have a 100% uptime, but this will get you close.
A background service, if not visible by the user will always be killed earlier or later by the Android system. It is the way memory management work.
If you really need to make a service continously run, you need to show a permanent notification to the user (like when you are using a radio app or a music player app).
What whatsapp and facebook probably do is to wake up the app remotely with any sort of messaging such as Firebase Cloud Messaging (ex-Google Cloud Messaging) or using Broadcast Receiver on certains events... But it surely isn't en ever going on service.
Read this part of Android documentation to better understand this:
Service Process Lifecycle.
As you can see, to give priority to your service process you will need to start it in foreground and pass it an Ongoing Notification using startForeground(int id, Notification notification).
Use setOngoing(true) in your NotificationBuilder to set a Notification as an Ongoing one: setOngoing(boolean b) doc.
Finally you usually want to add action in your Ongoing Notification (such as Player controls or the possibility to close the notification and hence your service when memory will be collected)
Here a full sample code:
Notification notification = new NotificationCompat.Builder(this)
.setContentTitle(getString(R.string.notification_title))
.setContentText(getString(R.string.notification_text))
.setSmallIcon(R.drawable.ic_small_icon)
.setColor(getResources().getColor(R.color.colorAccent))
.setContentIntent(pendingIntent)
.setOngoing(true)
//.addAction(android.R.drawable.close_service,"Close", closeServiceIntent)
.build();
startForeground(Constants.NOTIFICATION_ID, notification);
It's not a good idea, check out this article. Using a service in this case is not a good approach.

Custom notification bar hiding the image when it is clicked

I am making a Radio like app in Android, in which I need to show the current playing channel in the notification bar with "Play/Pause" buttons. so what i need to do is that when user click on pause button song should be paused and play image should be displayed. I have done doing pause for sound from notification bar but now i need to show the play image instead of pause image, and i also need to put the seek bar to control the volume for music. Thanks in advance.
To update a notification, you simply call notificationManager.notify() again and pass it the same id that you gave it last time. if there's an existing notification with that id, it will update that one with the new information.
Typically for music playback or other persistent behaviors that the user should have control over, a foreground service is used. You use a regular Service and call startForeground(), passing it an id and a notification just like you would for NotificationManager. The benefit of this approach is that Android is less likely to terminate your service if it starts looking for processes to clean up as long as your service is running in the foreground. Updating the notification works the same way: call startForeground() again with the same id and a new notification object.

Dismissing MediaStyle notifications

New Android MediaStyle notifications in Lollipop don't have a dismiss button. Looks like there is already a bug for it on Google Code.
Does anyone know what's a good workaround for this issue until the bug is resolved?
Should we just delay switching to MediaStyle? Or use one of the actions as the dismiss button?
Adding on to #ianhanniballake's answer:
For Pre-Lollipop use:
notificationBuilder.setStyle(new NotificationCompat.MediaStyle().setShowCancelButton(true).setCancelButtonIntent(createPlayIntent());
For post-Lollipop:
To start a media-player notification one must have surely used startForeground() to start the Media Service as a Foreground Service. The problem now is that this Service is not dismissible. EVEN IF we set the setOngoing(false).
The best practice followed is to make the Service dismissible in the paused state. To do that, when your Media Service receives a Pause state callback, call stopForeground(false). This stops the service, but keeps the notification alive. And it can now be dismissed.
Happy coding.
One mechanism which appears to work quite well is make the notification ongoing while music is playing and make it not ongoing (allowing it to be swipe dismissed) when the music is paused. This seems to be the technique that Google Music already uses.
Easy but probably not the most suitable solution is to just add an Action with a 'close' icon. Then simply provide a PendingIntent which will trigger when the icon is clicked:

Does cancelling a Foreground Service's notification pull the service out of the foreground?

I understand that the newer Android APIs require you to start an ongoing notification when the foreground service is running to alert the user that something is running.
My users are asking for a way to override this default behavior and hide the notification anyway (understandably).
If I hold a reference to the notification and cancel it after I call startForeground(..), will Android pull the service out of the foreground?
No. There is unfortunately no way around this.

Categories

Resources