Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to implement permanent, regular, background location updates?

Tags:

android

The app needs an underlying feature that picks up locations and sends them to a server. This must happen regularly (approx every 1-5mins) but most importantly it must happen all the time, never stopping, protected against the OS shutting processes down to reclaim memory, and when the app itself is not running.

The following solutions have been suggested to me. I'm familiar with handling Android locations, the issue here is to ensure they continue, even if the app is not in memory, and to persist through memory reclaims.

  1. SERVICE. Use a service to collect location events and handle them. Use the boot and screen-on broadcasts to ensure the service is always running (and possibly also increase the service priority to protect from memory reclaims).

  2. ALARMS. I gather these can be shut down when memory is short. How would I protect against that? This seems an ugly solution as the locations will arrive on a schedule anyway, so it seems unnecessary to have another time-based component.

  3. LOCATIONS VIA BROADCAST. Locations delivered via a broadcast intent would mean I can then handle the location events in a broadcast receiver. Will these location alerts continue indefinitely? Will anything other than device shutdown or the app turning them off cause them to stop?

What's the most durable approach?

like image 875
Ollie C Avatar asked Sep 29 '11 11:09

Ollie C


People also ask

Which method is best suited for getting location updates?

Make a location request Once a location request is in place you can start the regular updates by calling requestLocationUpdates() . Depending on the form of the request, the fused location provider either invokes the LocationCallback.

How can I set my background location?

In order to enable background location access, users must set the Allow all the time option for your app's location permission on a settings page, as described in the guide on how to Request background location.


1 Answers

This must happen regularly (approx every 1-5mins) but most importantly it must happen all the time, never stopping, protected against the OS shutting processes down to reclaim memory, and when the app itself is not running.

This is not strictly possible, on a variety of fronts.

Let's take them one piece at a time:

This must happen regularly (approx every 1-5mins)

You may not be able to get locations, period, let alone every 1-5 minutes. The user might have all location providers disabled. The user might have the device in airplane mode. The user might be in a large building (blocking GPS) with poor connectivity (making the network provider unreliable).

never stopping

The user can always get rid of you via the Manage Services screen in Settings or a task killer. If they do so, particularly on Android 3.1+, your app will never run again for any reason until the user starts an activity of yours (e.g., via the launcher). The user could also uninstall your app, of course.

protected against the OS shutting processes down to reclaim memory

You cannot guarantee against this. You can reduce the odds, but that is it.


Now, let's look at your various solutions:

Use a service to collect location events and handle them.

From the way you phrase this (and subsequent sentences), you mean an everlasting service, one that is designed to run 24x7. By definition, this means that your app is running, which violates one of your rules. Assuming you relax this rule, this solution massively increases the odds that the user will get rid of your service, and it increases the odds that Android will get rid of your service. You can minimize the latter by use of startForeground().

ALARMS. I gather these can be shut down when memory is short.

Not that I am aware of. However, if the user gets rid of you, your alarms will be removed.

This seems an ugly solution as the locations will arrive on a schedule anyway

No, they will not. The time parameter on requestLocationUpdates() does not mean that "locations will arrive on a schedule anyway".

Locations delivered via a broadcast intent would mean I can then handle the location events in a broadcast receiver.

No, you cannot. You have indicated that part of your work will be to send this data to a server. You cannot reliably do that on the main application thread, as it may take too long. A getService() PendingIntent, pointing to an IntentService would be more reliable.

Will these location alerts continue indefinitely?

No. See below.

Will anything other than device shutdown or the app turning them off cause them to stop?

The user can get rid of your app (uninstall, task killer, Manage Services). The user can disable location providers. The user may enter an area where the location cannot be determined. Etc.

Also, the device may fall asleep, AFAIK. It's possible the system keeps a WakeLock for the duration of your registered request for updates. It's even possible that the system will use AlarmManager internally to arrange to wake itself up on your supplied period, so it does not have to keep the device awake continuously. However, you will want to test this thoroughly.

What's the most durable approach?

If the concerns in my previous paragraph are handled by the OS, your third option is probably the most robust. Use startForeground() in your IntentService() and call stopForeground() just before exiting onHandleIntent() -- even short-lived services started by AlarmManager may get killed off due to low memory, much to my surprise.

That being said, your desired behavior seems like it may consume more battery life than the user might want. Please allow the user to control the polling period, including an option for "never poll, I'll update things manually".

like image 110
CommonsWare Avatar answered Oct 25 '22 01:10

CommonsWare