Services, no more?

from the CommonsWare Community archives

At October 10, 2020, 3:51pm, vedy asked:

Hi Mark,
I know you advise against background services, but I just wanted to get more clarity on your position.
The Android platform has the Services API:

  1. To run a service in the background (on a service thread) initiated by an activity for the duration of the life of that particular activity. Is this still valid? isn’t that what coroutines do now?

  2. Run a service in the back ground independent from activities (event based or on schedule) , my understanding is this is what you advise against. and you prefer that this be done wither using push messaging from the cloud , or using the official WorkManager.

So in all is creating services based on Android Service API still relevant?


At October 10, 2020, 5:20pm, mmurphy replied:

IMHO, that was never valid. We did some of that in the very early years, while we were coming to grips with the SDK and while alternatives were clumsy or non-existent. But I have been steering developers away from that since at least 2014.

Any threading option works. Services are not background threads, and if you have UI in the foreground, you do not need a service to keep your process around.

Not exactly.

For scheduled work, yes, these are the current right answers. In the case of push messaging, that would replace scheduled polling of a server. However, bear in mind that neither offer precise timing and neither are reliable in the face of Doze mode, app standby, and aggressive battery management policies from various device manufacturers. So, I steer developers away from trying to rely on services (or anything else) for periodic work.


Roughly speaking, there are two categories of service in the modern era:

  1. A specific type of service, usually with a specific superclass, that handles a specific OS integration scenario. Examples include TileService (for notification shade tiles), AccessibilityService (accessibility APIs), RemoteViewsService (for supporting certain types of app widgets), and InputMethodService (for writing soft keyboards). In these cases, the OS supplies a base service class, and the OS binds to that service. We extend that base class and implement a specific API for whatever role we are trying to fill. Because these are bound to an OS process, they will run as long as the OS wants them to run, where that duration will vary on the type of service.

  2. Subclasses of Service for app use. Nowadays, these usually need to be foreground services, tied to a Notification, in order to be able to run for app-determined amounts of time.

So, for example, for my current consulting client, we have a foreground Service that runs for an app-specified amount of time. The reason for the service is because the app integrates with heart rate monitors via Bluetooth, and we need to forward that heart rate data along. However, the user may not be actively using their device at the time after starting the initial data collection, so a foreground service helps ensure that our process sticks around to be able to collect this data for as long as we need that to happen (an hour or less in this case). That’s a legitimate and necessary reason for having a Service, the cost being that it has to be a foreground service on modern versions of Android.

So, rolling back to:

A foreground service that reacts to events — such as getting heart rate monitor data off of a Bluetooth connection — is reasonable.