In the last post, we read about Bound services and how their lifecycle depends on the component which binds to them. There is a second kind of service, called started services, whose lifecycle is independent of any component. They may continue to run in the background for an indefinite time.

Due to this indefinite running nature, resulting in poor performance, Android 8.0 brought a lot of restrictions to started services and the Android system will kill a service running service without a foreground UI if they run for a long time.

Android is pushing you to use bound services like JobSchedulers for doing things in the background so that it is more efficient and it results in better performance. You should definitely think of using the existing bound services before attempting to create your own. There are cases where JobScheduler won’t help you, like map navigation or music play. In those cases, you should use a foreground service, which is also a started service, but with a UI (through notification). This will ensure that Android doesn’t kill it (or atleast until the shit happens).

Creating a service

All services require you to implement the onBind method. Since this isn’t a bound service, we are just going to return null

class RandomNumberGeneratorService:Service() {
    override fun onBind(p0: Intent?): IBinder? {
        return null
    }
}

Starting a service

To start a service, we need to use an explicit intent.

val startServiceIntent = Intent(this, RandomNumberGeneratorService::class.java).apply {
            action = START_SERVICE_ACTION
        }
startService(startServiceIntent)

On Android 8.0 and higher devices, calling startService from the background (like from Broadcast receiver) will result in an IllegalStateException. In that case, use startForegroundService and call startForeground within the Service, within 5 seconds, to start a foreground Service while your app is in the background.

Since on Android 8.0 and higher, non-foreground services are likely to get killed, we’ll make our service a foreground service. To do that, we’ll use the startForeground method inside the service. This method takes in two arguments, a notification id (constant) and notification.

On Android 9.0, Apps wanting to use foreground services must now request the FOREGROUND_SERVICE permission first. This is normal permission, so the system automatically grants it to the requesting app. Starting a foreground service without the permission throws a SecurityException.

In order to stop a foreground service from within a service, we need to call two methods:

An over-simplified look to stop the service is:

If you feel that you don’t need to hold on to the foreground priority, you can use the stopForeground method to remove from the foreground state, while allowing the system to kill it if needed. Note that this doesn’t stop the service, it just removes the foreground state of the service.

Restart behavior of service

The onStartCommand is called everytime the service is started using startService call so it will be called several times in the Service’s lifecycle. You have to provide in this method, how the service should react when restarted, or when the system kills it before completing. There are several flags as listed below :

Inside the onStartCommand, you can determine which restart mode caused this onStartCommand to run. You can know which among the beow two is true: