My little Android warehouse

Random thoughts about my experience as moonlight android developer.

Behind Activities: Android, Services, Background Operations and Threads

This time I want to share something I learned about working in background on android.

One of the biggest advantages of android over ios (or, at least, some ios version ago) is that your app is not sandboxed and can continue to live in background.

To perform background (not visible) work, all you need to know is how to use android services.

A service is a piece of an application that is allowed to be active even if the application is not in foreground anymore. The most commonly used example for describing a service is the music player, which need to continue to play music when your app is hidden by something else.

First of all, I want to remark a concept I had some problems with: a service does not have any relationship with threads! The service shares the main (ui) thread with the rest of the components of the app. This means that, if your app is in foreground AND you have a service active AND your service performs some time consuming operations, it will affect the responsivness of the gui (and you don't want to disappoint your user).
So, even if you are now able to perform some background work, if you expect it to be heavy, please move it inside a thread (or an asynctask) hosted by the service.

Another advantage of bringing a service on board is that your application will gain priority over the other apps. Android prefers to kill processes that do not have active services. On the other hand, this means that you should use services carefully if you don't want to drain your user's battery. If you don't need a service anymore, please kill it and restart it later (as pointed out from mark murphy in this old but interesting article: http://www.androidguys.com/2009/09/09/diamonds-are-forever-services-are-not/)

Said that, I am now going to list some typical service usage patterns

  • Listen and react to events from outside which need to be handled even if the application is not active (and maybe when the device is idle), such as location variation, accelerometer, incoming calls and so on
  • Tasks that need to be performed periodically, like polling a mail server every 15 minutes
  • Continuous tasks (like playing a song, or sampling the location with a very narrow interval) that need to be performed in background


I would say the first two are similar, and the third needs to be handled in a different way.


One shot tasks
If you need one shot tasks (like downloading your email), you could:

  1. start a service with an intent
  2. return START_NOT_STICKY in its onCommand callback
  3. start an AsyncTask to perform the heavy operations

    OR

you can use an IntentService. 

IntentServices are useful as much as they are little advertised.
If your service is an intentservice, it will be automatically hosted in its own thread. You can send it as many actions to be performed you want bundled in intents. They will be queued and handled one at a time.
You don't even have to bother if you need to shut the service down. It will automatically shut down when you return from the onHandleIntent call. Much simple, isn't it?

Here are some simple scenarios for using intent services:

  • Background operation triggered from user (such as a button): Just pack the command in an intent, and launch the service with the intent.
  • React to some broadcast event (such as some system broadcast event): Register a broadcast receiver in your manifest and then launch the intent service from its onReceive. You can't handle long running operations in the broadcast receiver, there is a strict time limit in broadcast handling.
  • Perform periodic tasks: Use an alarm manager and make it launch your intent service. I also remind you that using setInexactRepeating in this case will help your app to save more resources.


Long running tasks

If you need to need to perform long, continuous background operations, you have no options, and you need a classic service, returning START_STICKY in its onCommand() method.
Again, remember that in this case you need to perform time consuming operations inside a thread or an asynctask, because the service shares the same thread with the gui.






The next time I will try to write down some more practical stuff on how to implement activities and services communication.


If I wasn't clear enough, if you broke your phone trying to implement this advices, or if you think I'd better shoot in my foot than writing this ugly stuff in a very poor engRish, drop me an email fedepaol gmail.com .
If you liked this post, you can consider following me on twitter @fedepaol .


UPDATE: I am currently (23/01/2012) working on a library to be used to interact with a service using an intent service. In case you may be interested, you can find it here PostmanLib - Android webservice interaction