Tuesday, April 24, 2012

InfiniteWakefulIntentService

If you want to do work in a service in a background thread, Android provides a class called IntentService, which does everything for you (except doing the actual work ;)). Now, if you want to do the above and acquire a wakelock, so the device doesn't fall asleep while you're doing boring work, there's Mark Murphy's WakefulIntentService.

These are two great tools for developers, but I've come across a situation where I need the mentioned functionality, but instead of doing work and stopping immediately after it has finished, I had to wait for a callback to return. If you used a IntentService in this case, the callback wouldn't ever succeed, because the implementation of IntentService destroys itself immediately after onHandleIntent() returns.

In my case, waiting for the callback of Text-To-Speech was crucial, so I had to find a solution. After fiddling with threads, tasks, handlers, loopers and the like for a few hours, I figured that it would be easier to modify IntentService instead of make the callback blocking. That's what I came up with: InfiniteWakefulIntentService.


Besides acquiring a wakelock and doing your work in a background thread, this service allows you to queue up as much work as you want. The service will do job after job, until there is no more work to do. Most importantly, it will ask your every now and then implementation if all work is done, e.g. waiting for callbacks, via isFinished().

You can find a meaningless sample implementation here. The result of isFinished() depends on various factors:
  1. is the TextToSpeech helper already instantiated?
  2. is TextToSpeech service ready for work?
  3. has the TextToSpeech helper finished emptying the queue?
  4. has TextToSpeech finished speaking?