Many of us know that (in loose terms) a
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. ...
stopService() or stopSelf() does not actually stop the service until
all clients unbind.
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
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).