2

So I need to send coordinates from my current location to a server, in very short frequences (30 seconds). Right now I am doing it with AlarmManager setRepeating(), but Android 5.0+ allows intervals from up to 1 minute to save battery.

My question would be:

Is my way really efficient? I need to run this repeating alarm in the background, even when the device is off. Currently I am executing pendingintent which leads to a broadcastreceiver which in turn executes to asynctasks, one for server authentication, one for posting the coordinates.

Peter David Carter
  • 2,548
  • 8
  • 25
  • 44
Mark Tyers
  • 93
  • 9

1 Answers1

1

Is my way really efficient?

No. This is why it is not supported out of the box on Android 5.1+, and this is why Android 6.0 introduced Doze mode.

I need to run this repeating alarm in the background, even when the device is off.

I assume that by "the device is off" that you really mean "the screen is off". If the device is powered down, your code will not run.

You can use setExact() to "manually" do your own repeating events on a 30-second interval, where the work that you do on the alarm event includes scheduling the next alarm. This too will fail on Android 6.0+ devices, when the device is in Doze mode. The only way to get every-30-second behavior on Android 6.0+ would be for the user to add your app to the battery optimization whitelist in Settings.

Currently I am executing the pendingintent which leads to a broadcastreceiver which in turn executes to asynctasks, one for server authentification, one for posting the coordinates.

First, that is unlikely to be reliable. Your process can be terminated as soon as onReceive() returns, since Android thinks that your work is done.

Second, AsyncTask is usually pointless from a background operation like a broadcast. The entire point behind AsyncTask is for you to do work on the main application thread when background work ends, and there is little reason to do work on the main application thread in the background. For this and the above reason, use a single IntentService to replace the two AsyncTasks.

Third, there is a decent chance that, on any given alarm event, you will be unable to complete your work in 30 seconds, due to network congestion, server issues, etc. You need to make sure that you handle this appropriately, so that you do not wind up queueing up all sorts of requests (or, in your current implementation, fork lots of parallel AsyncTasks all trying to do their work).

CommonsWare
  • 986,068
  • 189
  • 2,389
  • 2,491
  • As I understand correvtly, setExact() is not a repeating alarm, so how do I schedule a repeating alarm, for lets say, 30 seconds with setExact()? – Mark Tyers Jun 11 '16 at 19:53
  • @MarkTyers: Quoting my answer: "You can use `setExact()` to "manually" do your own repeating events on a 30-second interval, where the work that you do on the alarm event includes scheduling the next alarm". You indicated that your alarms trigger a receiver (hopefully a `WakefulBroadcastReceiver`). Have the receiver kick off the `IntentService` and call `setExact()` to schedule the next event. Or, have the `IntentService` call `setExact()` to schedule the next event, once the work is completed, to avoid queueing up work. – CommonsWare Jun 11 '16 at 20:07
  • So basically I have to set a `setExact()` for the `BroadcastReceiver` on Button press, and at the end of the code in the `BroadcastReceiver` I set another `setExact()`? And how do I stop it? – Mark Tyers Jun 18 '16 at 18:33
  • @MarkTyers: Call `cancel()` on the `AlarmManager`, or just do not schedule the next one (skipping the `setExact()` call), whichever makes more sense for your scenario. – CommonsWare Jun 18 '16 at 18:34