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.
Related
I am successfully able to monitor new app installation by dynamically registering broadcast in foreground service for Oreo and above version. But for this I always have to show a persistent notification of my app.
Is there any alternative to
Google in documentation says:
You should only use a foreground service when your app needs to perform a task that is noticeable by the user even when they're not directly interacting with the app. For this reason, foreground services must show a status bar notification with a priority of PRIORITY_LOW or higher, which helps ensure that the user is aware of what your app is doing. If the action is of low enough importance that you want to use a minimum-priority notification, you probably shouldn't be using a service; instead, consider using a scheduled job.
So can I use foreground service for this purpose. If not than what is its alternative.
As said in the doc you posted, consider using a scheduled job.
if you use a foreground service you will need a constant notification and that would be annoying for the user (plus you don't install new package every five minutes so ...)
Instead you should schedule a job to check if a new package is installed.
Look at the accepted answer in this question
You can also use polling, setting up a JobScheduler job to check every so often, asking PackageManager for what has changed in the roster of installed apps via getChangedPackages().
I am currently working on transitioning an application to Android O, and I am currently working on notification channels.
I have made different channels with different importance levels and since the application has a foreground service that has to run at all times until we transition to a new architecture (more push oriented), I thought about putting that notification in a channel that has its importance set as IMPORTANCE_MIN, so that it is there, but it doesn't bother the user, and doesn't place an icon in the status bar.
However, when I do that, and I put my application in the background (with Home or Back buttons), I get an Android System notification telling me that my app is running in the background, like so:
If I change my channel and make it use IMPORTANCE_LOW, the problem goes away, however, the notification is more prominent.
So, my question is - is it possible to do what I am trying at all? I get that the system would not allow the developers to do this, because if you have a foreground service, it should be visible to the user, but that's just a guess, and I found no documentation regarding this, and that's why I'm posting this question.
My second question is - prior to O, if you set the priority of your notification to PRIORITY_MIN, can you bind that notification to a service to make it a foreground service, or was that a no-go since always?
Edit: Confirmed that the Android System shows the notification for channels with importance IMPORTANCE_MIN (thanks, M66B), so the question that remains now is why? Does anyone know the reasoning behind this, or can find any documentation anywhere? Is this maybe a bug that should be reported to the tracker?
This behavior is now documented: https://developer.android.com/reference/android/app/NotificationManager.html#IMPORTANCE_MIN
Min notification importance: only shows in the shade, below the fold.
This should not be used with Service.startForeground since a
foreground service is supposed to be something the user cares about so
it does not make semantic sense to mark its notification as minimum
importance. If you do this as of Android version O, the system will
show a higher-priority notification about your app running in the
background.
And also here: https://material.io/guidelines/patterns/notifications.html#notifications-settings
In Android O, a channel’s default importance level for foreground
service notifications must be at least IMPORTANCE_LOW so that it shows
an icon in the status bar.
Channels using the less-prominent IMPORTANCE_MIN level will trigger an
extra notification from Android at IMPORTANCE_LOW, stating that the
app is using battery.
Sidenote:
This is a real pain for us, since prior to O we used to dynamically switch between PRIORITY_DEFAULT and PRIORITY_MIN when our foreground notification had no interesting information to present. With channels we can't change the IMPORTANCE dynamically anymore, and had to remove that feature.
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.
I didn't find any documentation about that. Is it possible to create a foreground service on android wear? Usually the foreground state is related with an ongoing notification but it's not possible on wear so I'm a bit confused. Is there anyone has a foreground service on wear?
As per documentation:
"The system enforces a timeout period. If you are displaying an activity and user's don't interact with it, the device sleeps. When it wakes back up, the Wear home screen is displayed instead of your activity. If you need to show something persistent, create a notification in the context stream instead."
So, i believe it's possible to have a persistent UI (may be not an ongoing foreground notification but a card or a stack instead).
Hope it helps.
I am looking at Avast, Lookout for example and I am trying to understand the concept of the implementation. So it is more like asking for direction for me.
Persistent App icon in Notification bar.
Am I correct to say there are function NotificationManager is able to do it?
Scan virus during app installation, I am not interested in virus scanning but the triggering mechanism.
Some kind of Android service bind to the main app?
Main app that can be bring up in the Notification menu.
A main app that remain trigger action to the bind services?
So what do I need to read to understand? NoticationManager, Services and ??
In short, I want to load a icon in the notification bar that can bring up my app. There is a background service that perform specific task for a set interval.
Yep, NotificationManager and Notification can help you with that.
You just need to create the notification with flag FLAG_ONGOING_EVENT (to make it persistent). Even better if your service IS REALLY performing some long-running task, if so, you can start your service via Service.startForeground which needs some 'ongoing' notification for running (notification is required to notify the user that there is some work going now).
For triggering app install event, you can use BroadcastReceiver with filter by Intent.ACTION_PACKAGE_ADDED.