Many of us know that (in loose terms) a Service
in Android will get killed by the system if it does not call Service.startForeground()
. But is this the whole story...?
I am working on some legacy code, porting a "system" permission app to the Play store. This app has 5 background services (that do not call startForeground()
), which until now, were safe, due to the "system" permission that the app ran with. It was installed on a custom device. Due to tight timelines and budgets, refactoring these 5 into 1 is not a short term solution, but we would like to move to open beta as soon as possible.
The short question is:
Activity
or Service
, does Android kill each individual background service, or does it just kill the process itself?Here is some info from the Android docs on Processes and Threads that discusses how Android will terminate processes when under pressure:
Android might decide to shut down a process at some point, when memory is low and required by other processes that are more immediately serving the user. Application components running in the process that's killed are consequently destroyed. A process is started again for those components when there's again work for them to do.
When deciding which processes to kill, the Android system weighs their relative importance to the user. For example, it more readily shuts down a process hosting activities that are no longer visible on screen, compared to a process hosting visible activities. The decision whether to terminate a process, therefore, depends on the state of the components running in that process. ...
Common knowledge says that "Android will kill the Service"
Personal experience has shown that Android will also kill the process itself (as described in the quote above). This can be shown by storing objects in the Application
object, and noting that they get reinitialised after the service is killed.
With the above in mind, there are a few options for solving the problem:
Refactor the 5 services into 1, running on various different threads. Bring the 1 service into the foreground. Problem solved.
Unfortunately no budget for this at the moment, and we would prefer to find a quick fix due to project timelines.
This is the final solution that will be implemented going forwards into full production.
Start each service in foreground, each with its own Notification
icon.
This is a messy solution, but will work for the beta field trials, buying us some time.
I think of this as the "brute force" approach.
If it is the process that is killed, rather than each individual service, then it will be good enough to have a single foreground service running.
This would "prevent" (i.e. lower the probability of) Android from killing the process.
All 5 services would thus survive.
The docs on Services tell us that if a service is bound to another context, then
stopService() or stopSelf() does not actually stop the service until all clients unbind.
If I bind to the other services from a single foreground service, will that keep them all alive?
After 18 41 hours of testing #3 (Process protected by one Service), all 6 services are still running (5 old plus the 1 new).
So it is looking as if Android would kill the process if no foreground activities or services are running.
For Problem 2, services can be killed when memory get low or manually by the user, so as others have pointed probably using AlarmManager to restart your service after a certain time will help you to have it running all the time.
The short question is: Android might decide to shut down a process at some point, when memory is low and required by other processes that are more immediately serving the user. Application components running in the process that's killed are consequently destroyed.
An Android activity goes through six major lifecycle stages or callbacks. These are: onCreate() , onStart() , onResume() , onPause() , onStop() , and onDestroy() . The system invokes each of these callbacks as an activity enters a new state.
First, the easiest way to do what you're trying to do is to launch an Android Broadcast when the app is killed manually, and define a custom BroadcastReceiver to trigger a service restart after that. Dear Dr Sabri Allani, If your Service is started by your app then actually your service is running on main process.
If there is no foreground Activity or Service, does Android kill each individual background service, or does it just kill the process itself?
Android does not kill individual Activities
or Services
, that wouldn't make much sense. For example if an Activity
is in the background Android will never decide to specifically kill this one Activity
. It doesn't matter what kind of Java Object
is in memory all those Object
instances share the same fate: If they are no longer needed/used they will be garbage collected. People often talk about an Activity
being killed when it is in the background and that is really misleading because they just mean it can be garbage collected and eventually will be. So this garbage collecting is what would destroy a specific instance of an object. It has nothing to do with the device having low memory.
When Android is running out of memory it will decide to kill a whole process, and as you already read in the documentation it chooses the least important ones.
What I'm trying to tell you is that those are two fundamentally different processes. One is the Android OS killing not important processes when its running out of memory and the other one is the garbage collector which is constantly looking for no longer used memory which it can free.
Common knowledge says that "Android will kill the Service"
As I explained above, this can be misleading and is not completely true, if the device is running out of memory it will kill the whole process, not just a specific Service
. This is different from the Service
being garbage collected when it is no longer used.
And now on to your solutions:
Refactor the 5 services into 1, running on various different threads. Bring the 1 service into the foreground. Problem solved.
This obviously is the best option but as you said you are not able to implement this now.
Start each service in foreground, each with its own Notification icon.
This would be a kind of bad solution, there is no reason to have multiple notifications. The other options are clearly better.
If it is the process that is killed, rather than each individual service, then it will be good enough to have a single foreground service running.
This could definitely work, I would try it.
The docs on Services tell us that if a service is bound to another context, then
stopService() or stopSelf() does not actually stop the service until all clients unbind.
If I bind to the other services from a single foreground service, will that keep them all alive?
This is the next best option in my opinion.
I initially thought about starting each Service
in its own process. But I am not sure if this is applicable to you. Especially if you want to keep all Services
running at all times. The benefit of starting a Service
in its own process is obviously that it is independent from the rest of the app. So even if some part is killed due to memory constraints the rest of the app will keep running in the other process.
Have you ever thought about using inheritance to solve the problem? It might be the simplest way to implement your option 1).
Every android application is a fork of zygote process and has its own process. Each application process can host more activities and services: so definetely, killing one process (example: kill PID) will kill everything which is inside.
By default a service is in the same process of its application; however it is possible, to let a service running on a dedicated separate process, with declaration in the manifest:
<service android:name=".MyService"
android:isolatedProcess=true />
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With