Uncategorized

Periodic background tasks in Android

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:

  1. Updating your android manifest xml
  2. Setting up broadcast receivers to listen to relevant events
  3. Set up a background service for context when your application isn’t running
  4. Initial start up from your application context

The Android Manifest

On that note, we’ll start by editing our AndroidManifest.xml.

As with most features that deal with Android application development, everything starts here. The lines we should pay attention to are the receiver and service tags and their contents.

The 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.

The service tag is sort of like declaring an activity without a UI. It will be used as the context for our background process.

Broadcast Receivers

Now let’s take a look at our first implementation of a broadcast receiver PeriodicTaskReceiver.java:

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 AndroidManifest.xml.

The actions this broadcast receiver listens for are and why:

  • android.intent.action.BATTERY_LOW:
    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.
  • android.intent.action.BATTERY_OK:
    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.
  • com.example.app.PERIODIC_TASK_HEART_BEAT:
    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 restartPeriodicTaskHeartBeat and 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 BootAndUpdateReceiver.java:

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:

  • android.intent.action.BOOT_COMPLETED:
    The broadcast sent when our device has completed booting up from a system restart.
  • android.intent.action.MY_PACKAGE_REPLACED:
    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.

Application Context

Lastly, the way we kick everything off using the Application context MyApplication.java:

Conclusion

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.

Discussion

14 responses to ‘Periodic background tasks in Android

    • @Bolein doPeriodicTask is an async task which means you are not calling it directly (it is run on a schedule). If you need to access variables from an activity you could either save the variable as an argument in your shared preferences if it’s primitive enough and fetch from there, or create a setter/getter around an instance variable in your Application context since that is available in the doPeriodicTask method.

  1. Hi
    Thanks for this guide, but it would be great if we can have access to the full example code.
    I’ve noticed that restartPeriodicTaskHeartBeat method of the receiver is called from BackgroundService with only one argument (BackgroundService.this).
    Thanks in advance

  2. Thanks, one thing, I noticed isAlarmUp never fires as the intent checked for is not exactly like the one started (the one started has the context + receiver class set) 🙂

  3. Hello! This is my first visit to your blog! We are a
    group of volunteers and starting a new initiative in a community
    in the same niche. Your blog provided us beneficial information to work on. You have done a wonderful job!

  4. Hi Tashafa,
    It seems to be very simple for experienced guys, but I’m very new to this, learning on my own, and I came to the point to be in front on a black box.
    All I need to do is to play an alarm at specific date and time, reading that info from a DB, even when the app is running or not.
    I read the article, the android manifest and the rest of things, to me is still a puzzle, and can’t put the shapes together.
    Would it be possible to go a little bit further for really rookies as me?
    Thanks and have a nice weekend

  5. Dear Tashafa,
    I am with Ovidio on this, coming from the old C world there are way too many unknown things to get a simple task like this working. I have tried to use the examples as they seem to be the only one taking into account battery levels (which is important for my task), but I cannot get this to work.

    Placing snippets in github that doesn’t work is not really helpful, and while I probably should get a beginners course in oo-programming, this quite simple task eludes me. I have managed through other examples using the alarm manager to get it working, but your example seems like the right way to do it. Any chance of a working example? (as whatever I trie to do fails, and the manifest is now blocking me totally).

    • Hi, Jonas
      You might want to look at some fresher articles than this one. There have been some important changes in scheduling and executing background tasks since the article was written.
      Please check out Sync Adapter and JobScheduler classes

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

Pingbacks & Trackbacks

  1. Complex Android Home Screen Widgets | Jana Technology