I’ve been struggling these days trying to find a way to run an endless service in Android. This is just a guide for all of you who pursue the same goal. Hope it helps!
Due to Android battery optimizations introduced in Android 8.0 (API level 26), background services have now some important limitations. Essentially, they are killed once the app is in background for a while making them worthless for our purpose of running an always-running service.
Unfortunately, this won’t work either. JobScheduler will run jobs at Android’s discretion and, on top of that, once the phone enters in Doze Mode, the frequency of these jobs being run will constantly increase. And even worst, if you ever want to access the network -say you need to send data to your server- you won’t be able to. Check out the list of restrictions Doze Mode imposes.
JobScheduler works well if you don’t mind about not having access to the network and you don’t care about not controlling the periodicity either. In our case, we want our service to run at a very specific frequency and never be stopped, so we’ll need something else.
It’s all about Foreground Services
If you’ve been looking over the internet for a solution to this problem it’s very likely that you’ve eventually arrived to this page from the Android’s documentation.
There, we are introduced to the different types of services that Android provides. Take a look at the
Foreground Service description:
A foreground service performs some operation that is noticeable to the user. For example, an audio app would use a foreground service to play an audio track. Foreground services must display a Notification. Foreground services continue running even when the user isn’t interacting with the app.
It seems to be precisely what we’re looking for… an it is, indeed!
Show me the code
foreground service is really a straight-forward process so I will visit and explain all the steps needed to build a foreground service that never stops.
As usual, I’ve created a repository with all the code in case you want to take a look at it and skip the rest of the post.
Adding some dependencies
In order to add these dependencies we must add them to our
Writing our service
Foreground Services need a notification to be shown so the user is aware that the app is still running. That makes sense if you think about it.
Note that we will have to override some of the Service callback methods that handle key aspects of the service lifecycle.
It’s also very important that we use a partial wakelock so our service never gets affected by Doze Mode. Bear in mind that this will have an impact in the battery life of our phone so we must evaluate whether our use case can be handled by any of the other alternatives Android offers in order to run processes in the background.
There are some utility function calls (
setServiceState) and some custom enums (
ServiceState.STARTED) in the code, but don't worry too much. If you want to see where they come from, just take a look at the example repository.
Time to deal with the Android Manifest
We will need some extra permissions for
WAKE_LOCK. Be sure you don't forget to include them because it won't work otherwise.
Once we put them in place we will need to declare our service.
Can you tell me how I start the service?
Yes, you’re right. You see, depending on the Android version we must start the service with a particular method.
Here you can see our
MainActivity, just a screen with two buttons to start and stop the service. That's all you need to start our endless service.
Remember that you can check out the complete code in this GitHub repository.
Bonus: Start the service on Android boot
Ok, we now have our endless service making network requests every minute as we wanted but then the user restarts the phone… and our service doesn’t start again… :disappointed:
Don’t worry, we can find a solution for this, too. We will create a BroadCastReceiver called
Then, we’ll modify again our
Android Manifest and add a new permission (
RECEIVE_BOOT_COMPLETED) and our new BroadCastReceiver.
Take into account that the service won’t be rebooted unless it was already running. That’s how we programmed it, it’s not that it has to be like that.
Anyway, if you want to test this, just spin up one emulator with
Google Services in it and be sure to be running adb in root mode.
Originally published at https://robertohuertas.com on June 29, 2019.