---
In a couple of previous posts I have shown how to implement a never ending service using different methods. Unfortunately those methods no longer work in Android after 11.
Android has defined a new set of constraints that require that no background or foreground services can be created when the app is not in the foreground (i.e. it is not in use by the user). This puts some severe constraints on the creation of never ending services. Especially if those services are unstable and die at some point in time.
Therefore it is imperative that:
- the services are stable and do not stop and restart: once started they must stay for as long as they are needed - it will not be possible to restart them
- the services are started at an appropriate time (i.e. at reboot or when the app is installed/reinstalled).
I have developed an example that provides a service that counts constantly from zero to infinite, incrementing every 2 seconds.
The architecture is composed of:
- a broadcast receiver receiving the message that the phone was rebooted or the app (re)installed: class RestarterBroadcastReceiver
- a coroutine worker (MainCoroutineWorker) that will be started when the broadcast is received and will launch the never ending service. In case you are unfamiliar with the concept of a co-routine worker, this is a Jetpack class that takes care of implementing a task that needs executing independently from the status of the application. Once planned, it will be executed no matter if the app is open or closed. The type of worker that we implement is of type coroutine, so it implements suspended processing, i.e. async processing. The good thing about workers is that they take care of the complexity of coping with different versions of Android, i.e. they will implement a JobService in Android>9 or a broadcast receiver + a foreground service in previous version. Our Worker starts immediately and executes urgently as we have just very short grace period for launching the service after reboot/reinstallation. The computation is executed in the Dispatch.io context, which is a context for I/O-heavy computation. This is because I have derived this example from an application doing heavy I/O in the service. You could use other Dispatches (bar the main dispatcher, as you do not want to run on the UI thread). If you are not familiar with coroutines, dispatchers and threads, you should really look into JetPack as in my view you cannot call yourself an Android programmer without knowing JetPack and Kotlin well.
- a foreground service implementing the infinite counter (CounterService)
The example uses an MVVM architecture organisation. If you are not familiar with MVVM, you should really look into it. It is the way modern Android applications are organised. It allows the separation of concerns between the View (i.e. the UI) and the model itself (in this case our counter). Model and View can communicate using LiveData defined in the ViewModel.
The full code can be found on Github. As usual for my posts the licence is MIT so you can use the code as much as you like for any purposes you want, including commercial reasons. No need to ask.
The Broadcast Receiver
The it will enqueue the task and wait for it to be executed.
The coroutine worker
The service
Note that the service has been quite simplified with respect to that version: there is no emergency restart in case it is killed. The launch from the Worker allows the service not to be stopped as often as it used to be normally in Android. The only part that has become overly complicated is the creation of the notification as notifications have changed over the years and you have to consider previous versions of android as well.
Live Data
In the view Model the variable is defined as:
The part of the service incrementing the counter is pretty easy
That is all!
Those of you who looked at the code for Android <7 and Android 7 to 11 will realise that the code has simplified considerably thanks to the use of JetPack. However you are required to know well the latest development in Android and that is in any case a requirement for every excellent Android programmer
Does your process still stop?
These will be discussed in the next blog entry.
Change Tracker
06.10.2022: removed the observers when the app enters onPause - this was likely to create warnings and misbehaviour
11.10.2022: added the "Does your process still stop?"
Thanks
Thanks to Omar Brugna for identifying and correcting a couple of issues in the code