5

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.

Mr_and_Mrs_D
  • 32,208
  • 39
  • 178
  • 361
  • Your users will probably kill you if you keep a `Service` alive continuously draining their phone's battery just to gather dome data at certain time intervals. Use the second approach, with an `IntentService` with additional WakeLocks if needed(have a look at CommonsWare's `WakefullIntentService`). – user Mar 16 '13 at 16:06
  • @Luksprog : thanks - would I need locks ? in the broadcast receiver which would receive the alarm (still looking into how exactly should this be implemented) ? – Mr_and_Mrs_D Mar 16 '13 at 16:10
  • Why the negative vote ? – Mr_and_Mrs_D Mar 16 '13 at 21:11
  • I didn't downvote your question but someone else didn't liked it. Don't be too stressed about that. – user Mar 16 '13 at 21:37
  • @Luksprog: Yes no prob - I didn't think it was you :D - I hate downvotes for no reason - and anyway it's not a bad question or anything - duh – Mr_and_Mrs_D Mar 16 '13 at 22:43

3 Answers3

6

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.

CommonsWare
  • 986,068
  • 189
  • 2,389
  • 2,491
  • Thanks - why register the BroadcastReceiver in the manifest (not the Boot one - this must be there) ? Wouldn't this mean that it will be registered all the time - resulting in some overhead ? While BootReceiver -> `is monitoring enabled ? (register a receiver for the alarm; set up the alarm) : return` seems more economical. Also the AlarmReceiver will run in my main UI thread ? This would be the case when my activity (which just displays data collected and allows enabling/disabling monitoring) is up - no ? Otherwise there would be no UI thread (or it would not make a difference)- am I wrong ? – Mr_and_Mrs_D Mar 16 '13 at 16:25
  • @Mr_and_Mrs_D: "why register the BroadcastReceiver in the manifest" -- otherwise, you need to keep a component (e.g., Service) around all the time, which is the point behind switching to `AlarmManager`. You do *not* want to be taking up memory all of the time. "Wouldn't this mean that it will be registered all the time - resulting in some overhead ?" -- it will only be used by your `AlarmManager`. "Also the AlarmReceiver will run in my main UI thread ?" -- `onReceive()` of `BroadcastReceiver` is called on the main application thread. – CommonsWare Mar 16 '13 at 16:28
  • @Mr_and_Mrs_D: "Otherwise there would be no UI thread" -- there is always a "UI thread", more accurately referred to as the "main application thread". If you spend too much time on the main application thread, even from `onReceive()`, Android will terminate your operation. – CommonsWare Mar 16 '13 at 16:29
  • Ok - I have to read up on BRs - I thought that if I registered the receiver in the boot receiver - or in my app whenever the user enabled monitoring I would be fine. Will have a look at the code posted and come back for more - as there are many small details escaping me :) – Mr_and_Mrs_D Mar 16 '13 at 17:04
  • @CommonsWare. Any idea how does app like whatsapp, fb works so smoothly - almost real time and with not much battery drain. Can you recommend any sample application for that. I love your books and blogs and it will be great if you can write a blog post on it. I found many to be confused (including me) and saw all your answers on stack overflow. – Harshit Bangar Oct 27 '15 at 05:13
1

use second option , and should use intentService + AlarmManager see this example http://www.dotkam.com/2011/01/10/android-prefer-alarms-and-intent-receivers-to-services/

0

Depending on the length of the recurring task you can choose one of several approaches. This question discusses them - Scheduling recurring task in Android

Using an AlarmManager is convenient when task sleep times are 15 minutes or longer. The pattern is well known.

Community
  • 1
  • 1
Deepak Bala
  • 11,095
  • 2
  • 38
  • 49
  • @CommonsWare : I have similar situation to perform some task(GPS Positioning) on interval of 1 min. I am using Handler for that in my Main Activity how will it affect my application – Tushar Jun 01 '13 at 19:20