There comes a time in android application development you may need to run a process on a device when users are not particularly interacting with your application. You might need to do this at a set time, at specific intervals, or on a schedule. Some use cases that come to mind are enabling location services for contextual data of nearby points of interest a la Foursquare’s timely notification tips, or connecting to an external resource to refresh data when you determine your data is stale without the user having to interact with the application.
This post serves as an explanatory guide on how to achieve this from the ground up. It comes from cherry picking what I determined were appropriate solutions from StackOverflow to Google’s official Android resource et al. We also attempt to solve common problems developers face running a background service, from managing battery consumption to making sure your service remains active during different app and device states.
The literacy of this article assumes that you are an intermediate Android developer, which means knowing your way around the Android manifest, starting activities, creating intents, or editing shared preferences; the basic stuff.
The steps will involve:
- Updating your android manifest xml
- Setting up broadcast receivers to listen to relevant events
- Set up a background service for context when your application isn’t running
- Initial start up from your application context
The Android Manifest
On that note, we’ll start by editing our
As with most features that deal with Android application development, everything starts here. The lines we should pay attention to are the
service tags and their contents.
receiver tag and accompanying child tags allows your application to listen to “intents” broadcasted by either our application, the Android OS, or other applications. It accomplishes this by declaring a class that implements a
BroadcastReceiver by referring to said class in the
android:name attribute. In this case we are listening for distinct events described in the aforementioned child tags namely the intent-filter tag and its children action tags. We are teasing out intents for our background service pertaining to actions about battery status, application updates via app stores, device boot up completion, plus our own generated broadcast which is the heart beat of our background process. After we demonstrate our implementations of a broadcast receivers, there will be a more detailed dive into these intents thereafter.
service tag is sort of like declaring an activity without a UI. It will be used as the context for our background process.
Now let’s take a look at our first implementation of a broadcast receiver
Most implementations of the
BroadcastReceiver class override the
onReceive method. This method is called with an intent that matches one declared in the intent filter of the
receiver tag in the
The actions this broadcast receiver listens for are and why:
Broadcasted when the battery on the device reaches below a certain threshold. We use this intent to stop our background process to preserve the battery of the device. This is purely optional power management feature but recommended in cases where the background service may be a burden on the battery life of the device. In the code above, we save a flag, which acts as a control to determine if we should start the tick at all, in our shared preferences denoting the status of our battery during this broadcast.
The counterpart of the intent above is broadcasted when the battery on the device rises above a certain threshold. We attempt to restart our background task when we receive this intent also recording the battery status control flag in shared preferences.
Our application’s own broadcast, created and sent from our restartPeriodicTaskHeartBeat method.
The logic behind our broadcast receiver class should be straight forward at this point with the exception of the inner workings of the
stopPeriodicHeartBeat methods. These methods are used to stop or restart the broadcast of our heart beat
com.example.app.PERIODIC_TASK_HEART_BEAT at certain intervals using an alarm system service. The
restartPeriodicTaskHeartBeat method also includes logic that will fail to reactivate our broadcast if the battery control flag is set to signal that the device is currently below the low battery threshold or the broadcast has already been scheduled.
Also in the
restartPeriodicTaskHeartBeat method, our application’s broadcast or heart beat is created using an
AlarmManager that provides access to the alarm system service running on the Android operating system. An alarm service allows for a background task to be run at scheduled times, and not to be interrupted at various states of the device. (note: Alarm services are stopped when the device is rebooted and will need to be restarted at boot time. More on that later) The most important line that affects the behavior of the broadcast is:
They are a lot extensive ways to change the behavior of an alarm manager which are too numerous to cover here, but in our implementation, we are using the method setInexactRepeating which broadcasts our intent in a fashion where it bundles up other alarms from other applications that are set to go off at that approximate time, firing them simultaneously. This is a battery saving feature that does not wake the device unnecessarily if there are other pending intents that are set to go off on a similar schedule. The first argument of this method
AlarmManager.ELAPSED_REALTIME_WAKEUP, ensures the device is woken up when the intent is broadcasted as opposed to
AlarmManager.ELAPSED_REALTIME which will start your intent the next time the device is woken up either by the user or by another alarm intent that wakes up the device. You can read up on more details about Alarm managers and the variety of options in the official Android reference about AlarmManagers.
And now for our second broadcast receiver
The broadcast receiver simply attempts to restarts our
Service implementation (which will be covered later on) when the device is either powered back on or the application is updates via the Google PlayStore. The two intents it takes to achieve this are:
The broadcast sent when our device has completed booting up from a system restart.
The broadcast sent after our application is updated.
The Background Service
Our background service implementation, which serves as a context for our background task,
BackgroundService.java is up next:
In this implementation, the service tries to find the device’s low battery threshold and set our battery control flag appropriately before it attempts to restart the heart beat of our periodic task receiver. Some devices are missing this resource, so we’ve set a default threshold (0.14f in this case) and wrapped the check in a try/catch block.
Lastly, the way we kick everything off using the
I hope this helps as a guide for making your background service in your Android application user and device friendly. Feel free to fiddle around with the plethora of options and settings from the Android documentation to meet specific requirements in your application.
If I have gotten something wrong or your implementations are exhibiting weird behavior, please let me know.