I have a question about BroadcastReceivers. I have an app that needs to receive constantly the ACTION_TIME_TICK intent to refresh the clock widgets. I implemented a foreground service which contains a BroadcastReceiver that listens to that action. But on android oreo the only way to start a service is starting it as foreground service which implies to show a persistent notification to the user which notify that the app is working in background.
I don't want to show to the user that notification. I tried to implement BroadcastReceiver inside the Application class. But this is not working proprely. Somethimes the BroadcastReceiver doesn't work and somethimes works well. Even when it works well, if the app is removed from the recent tasks, the BroadcastReceiver stops to work. Is there a way to use a BroadcastReceiver that works indefinitely without the use of a service?
Is there a way to use a BroadcastReceiver that works indefinitely without the use of a service?
In the case of ACTION_TIME_TICK: No, since you cannot use a manifest-declared BroadcastReceiver.
Since you're not willing to use a foreground service, you may want to look into START_STICKY. In this situation, that's the only way to maximize your Service's run-time: Allow the system to re-start it, capriciously, after it's been stopped for lack of resources. Of course, this means your clock could stop updating for arbitrarily long periods of time.
Note that your problem is not limited to Oreo (Oreo does not require you to be a foreground service, but it does impose certain limits on what you're allowed to do if you're NOT in the foreground). Even on earlier OSs, if you're not foreground, the system considers you a prime candidate for elimination.
Related
I've read that I should call
startForegroundService(intent)
if I want to properly start a service that can run as a foreground service. But how should I think if I want it to start without it being a foreground service but potentially becoming one later on? Some info on how we have it right now:
We have an App which uses a service for many tasks. It performs all of these task when the user interacts with the app in the foreground but depending on if the user has enabled a certain feature we want to keep performing these tasks in the background. So when the app is launched (and obviously is in foreground) we start the service using
startService(intent);
When the app transitions into background we check whether the feature is enabled, and if so, run startForeground(id, notificiation); which effectively adds the non-removable notification out in the OS and the service keeps on running. When the app goes back into foreground we call stopForeground(true). If the feature isn't enabled the service will never be set as a foreground service and we won't try to perform these tasks in the background.
So my question is: Is this sufficient to get the "full foreground service performance"? Or am I losing something by not calling startForegroundService(intent)? My impression is that we actually do have a fully working foreground service but I'm getting confused when I read statements that foreground services must be started using startForegroundService(intent) which we're not doing. If we really need to use startForegroundService(intent), the only solution I can think of would be to initially start a normal instance of the service and when the app enters background we start a new one using startForegroundService(intent). But do we need to do this or is running startForegund(id, notification) on a service started using startService(intent) sufficient to achieve a foreground service?
NOTE: One difference I find is that if the application itself is in background when start the service I then need startForegroundService(intent) for API >= 26. In our case we always start the service when the app is in foreground. I do however recall some instances where I've seen the exception thrown when we try to start the service using startService(intent), somehow the app (very very rarely) still think it's in background (perhaps something from the OS comes up just when app is launched). So if I catch when that happens I could run startForegroundService(intent) to start the service. But is it possible to run stopForeground(true) on that service when the app comes back into foreground? Or is it bound to be a foreground service forever since we started it that way?
Seems like you don't have to call startForegroundService and startService is sufficient:
If your service is started (running through Context#startService(Intent)), then also make this service run in the foreground, supplying the ongoing notification to be shown to the user while in this state. By default started services are background, meaning that their process won't be given foreground CPU scheduling (unless something else in that process is foreground) and, if the system needs to kill them to reclaim more memory (such as to display a large page in a web browser), they can be killed without too much harm. You use startForeground(int, Notification) if killing your service would be disruptive to the user, such as if your service is performing background music playback, so the user would notice if their music stopped playing.
From Documentation
I read your question multiple time and I think (hopefully) the answer to your question is :
According to the official document of Android 8.0 Background Execution Limits:
Android 8.0 introduces the new method startForegroundService() to
start a new service in the foreground. After the system has created
the service, the app has five seconds to call the service's
startForeground() method to show the new service's user-visible
notification. If the app does not call startForeground() within the
time limit, the system stops the service and declares the app to be
ANR.
So, make sure you have started ongoing notification by calling startForeground (int id, Notification notification) in the onCreate() method of your service.
Note: Apps targeting API Build.VERSION_CODES.P or later must request the permission Manifest.permission.FOREGROUND_SERVICE in order to use this API.
And there is great medium article posted by Maciej Witowski that help you understand how really new services API works :
https://proandroiddev.com/pitfalls-of-a-foreground-service-lifecycle-59f014c6a125
This is similar to another question I asked where I was wondering how other apps like drupe dialer keep their service running forever when it is not in foreground. Because I've used job services, alarm manager, START_STICKY and everything else to try to keep my service alive but it always gets stopped by the OS.
You can run the service as "Foreground" and it will be not candidate to be killed by the system under low memory conditions. The gotcha is that you will need to show that behavior to the user with a notification. This is the way that music players uses to go background and alive when you start another apps.
Foreground Services
The app you mentioned (Drupe Dialer) is a Dialer. It might be listening to broadcasts and turning the service up every time by checking whether its up.
To answer your question, you need to keep the service started as START_STICKY to make it restart after the OS kills it. But AlarmManager does not work at device sleep states, and doze will stop it from running in the background nevertheless.
The real question is; WHY you want to keep it running? That might answer your question on HOW you want to do that.
If its a communication type app, you will need to use something like
GCM.
If its running background work based on some event, you might
want to start the service inside the BroadcastReceiver.
etc.
it depends on what app you're writing.
I wrote an app which monitors my signal strength via a PhoneStateListener. I want this app to start up at boot time and run forever.
The way I managed this is as follows, but I'd like to know if anyone can recommend a better way of doing this.
I have registered a BroadcastReceiver which runs upon BOOT_COMPLETED.
Within this BOOT_COMPLETED BroadcastReceiver, I start a Service.
The Service starts up my PhoneStateListener.
Within my BOOT_COMPLETED BroadcastReceiver, I also start a periodic alarm via AlarmManager.setInexactRepeating.
Whenever this alarm fires off, it checks if my Service is running. If it's not running, it restarts my Service, which in turn restarts my PhoneStateListener.
This all seems to be working for me, but I'm wondering if it's the best and most efficient way to ensure that a PhoneStateListener is running all the time (or at least most of the time).
Is there perhaps a better way to manage this?
Thanks in advance.
You can make your service a foreground service, in this case your service is really unlikely to be killed (only if the currently opened app needs more memory).
In this case your app must show an ongoing notification to the user while the service is in foreground.
To do so, you must call the startForeground() method of your service, providing a notification to it:
startForeground(ONGOING_NOTIFICATION_ID, notification);
Check for more info: http://developer.android.com/guide/components/services.html#Foreground
I have a service with graphic elements, that needs to run for a few seconds then stops itself (all while the app itself is in background). But often times the system automatically closes the service due to low RAM.
I am new to android, and all the codes for bringing service in foreground are using IntentServices.
Can only IntentServices be brought to foreground? If yes, how can I prevent my service from closing.
See [startForeground()](http://developer.android.com/reference/android/app/Service.html#startForeground(int, android.app.Notification)) method of Service class. Do note that it requires you to provide a Notification.
I have a service with graphic elements
What exactly does that mean? A Service in Android is meant for the exact opposite use case - i.e., when there is no user interaction desired.
I am working on an application which need to show notification constantly.
I've a service to show the notification every seconds.
When the resources goes low android is killing my service.
I've given the return START_STICKY from onStartCommand().
So after some time the service is getting restarted.
But in the mean time the notification look stoped.
I red somewhere that it is possible for a service showing notification prevented from getting stoped by android. I dint get any example for it.
Use
startForeground(int,Notification);
in onCreate of service. It requires a notification number and a notification object which it will display in the notification bar.
To remove the notification, use
startForeground(0,Notification);
As written above you need to use startForeground(int,Notification) method to aware user about your service. It also get more privilage for it.
You can read more about it here (example inside).
There is no way to completely stop it from ever being killed. Making it a foreground service helps. Returning start_sticky means it will be restarted if it is stopped (so it should do a startService on itself in its onCreate to make sure it restarts and not just gets recreated). But Android has the right to kill any service at any time due to resources.
Update:
You can use Foreground Service in the scenario. From the docs:
A foreground service is a service that's considered to be something the user is actively aware of and thus not a candidate for the system to kill when low on memory. A foreground service must provide a notification for the status bar, which is placed under the "Ongoing" heading, which means that the notification cannot be dismissed unless the service is either stopped or removed from the foreground.
In my knowledge there is no bulletproof way of preventing your service from being stopped by the android system. If the device is critical on memory/resources then your service has to be stopped for GC. This is also not recommended because your service will drain the device battery.