Android design : background long running service or AlarmManager?

Mr_and_Mrs_D picture Mr_and_Mrs_D · Mar 16, 2013 · Viewed 10.9k times · Source

I am building an app which will monitor the battery state, wifi connection and location data at regular intervals and will write the results in a file (and later send them off to a server). On installing the app monitoring should be disabled - but the user enabling it should survive a reboot. After a lot of reading I have realized that I have basically 2 options :

  • Subclass Service and fire it off from my activity. Set it on foreground, STICKY and what not and hope that it is not killed by android - and take care if android recreates it (actually there should be 3 services so syncing between them could be messy). Start a thread in the service (no need for Executors I guess) and have it Thread.sleep(REGULAR_INTERVAL). Wake up, collect the data write them to a file. Broadcast the collected info and display it on my activity if it happens to be running (which will have registered a Broadcast Receiver). Rinse and repeat while(true). Have a way to interrupt this
  • Have my activity register a PendingIntent with AlarmManager - which will run every REGULAR_INTERVAL. I haven't looked into the technical details of this approach so much - but I hope I will be able to make this PendingIntent create and run an IntentService (this seems the way to go - having the Thread machinery for free as well as shutting down on its own). Some skeleton code for this approach would be welcome.

I think I have to register a boot receiver in both cases to check the Shared Preferences (have already done this) and in case 1 start the service(s) while in case 2 register a Receiver for the alarm event and set the alarm manager up - that is the part I need some skeleton code.

So - before I start building this - which would be the preferred approach ?

In recap - the app should monitor some phone properties and write them to a file till the user chooses to shut it off.

Answer

CommonsWare picture CommonsWare · Mar 16, 2013

while in case 2 register a Receiver for the alarm event and set the alarm manager up

Your receiver will already be registered via the manifest.

which would be the preferred approach ?

AlarmManager, assuming REGULAR_INTERVAL is typically decently long (e.g., over a few minutes). Ideally, that interval is user-configurable.

If you intend to do this even when the device is otherwise asleep, your option #1 simply will not work, unless you keep a WakeLock on all the time, which will cause your users to want to shoot you in the face with a shotgun.

Some skeleton code for this approach would be welcome.

Here is a sample app demonstrating the use of AlarmManager for non-_WAKEUP alarms (i.e., you only need these events to occur while the device is already awake for other reasons).

Here is a sample app demonstrating the use of AlarmManager for _WAKEUP alarms, using my WakefulIntentService. WakefulIntentService (or something like it) is necessary because AlarmManager does not keep the device awake very long (just long enough for onReceive() of a BroadcastReceiver), and so you need to take additional steps to keep the device awake long enough for you to do your work. Theoretically, your work might be quick enough to do just in onReceive() of a BroadcastReceiver, avoiding the need to mess with the WakefulIntentService. However, you will be doing disk I/O each of these times, which ideally should not be done on the main application thread, where onReceive() is called. And, when you go to upload your data, you may well need a WakefulIntentService then, anyway, if you are looking to do that in the background as well.