Requesting geolocation with a minimum accuracy requirement - android

Suppose I'm bound to use one provider, say GPS. I have a minimum accuracy requirement and I need a single signal that satisfies it. What are the best practices?
What I'm doing is I call "requestLocationUpdates" to get continuous locations, then check each one for accuracy and finally call "removeUpdates" when I get a good one.
Should I be doing this with minTime and minDistance set to 0 because the accuracy comes randomly enough? Or should I set some special values to it because, by the nature of GPS, it's likely to keep giving me similar accuracy unless I move away (say from buildings?) or I give it time (say for random atmosphere conditions or satellite positions to change?)? If so, which values would it be?
Note: According to this text, GPS uses more power to get the fix than to get locations afterwords. Which for me means that "requestSingleUpdate" is no good with an accuracy requirement. Is this right?
If you're using NETWORK instead, will it work in the same way?

In your case only solution works:
Set Provider to GPS only, set time and accuracy to best (0),
and decide yourself, e.g by reading attribute estimatedAccuracy from location.
Its true, the initial position finding needs most power, so it makes no sense to enable and disable GPS every 20s. Unfortunetly I dont knwo where the threshold in minutes is where it saves battery when temporary disabling GPS.
The acuiracy requirement currently makes only sense to distinuish between GPS (3-6m) and Network (GSM cell: 1000m) WLAN sometimes will be better than GSM cell locationing, but often is not available, and less reliable.
If you, for your app decide that you need more or less acurate position, then an accuracy requirfement, other than "best" make no sense.

Related

How to most accurately determine the location of an Android device?

I'm building an app that should be able to report the users exact location. There is only a need for a single location, i.e. I don't need to track the device continuously.
I want the location to be as accurate as possible, and it's okay to wait a short while for the location to be determined (max 1-2 minutes).
I've been looking at FusedLocationProviderClient.getLastLocation(), but since I want the location to be as accurate and updated as possible it doesn't fit my needs.
So I started looking at using FusedLocationProviderClient.requestLocationUpdates() instead, and it seems like a better choice.
But I'm not sure how to best configure my LocationRequest to get as good accuracy as possible. For instance, would it be better to use setNumUpdates() so that I only receive a single update and use that as my location, or should I receive multiple updates in hopes of getting better accuracy (GPS locking to more satellites for example)? I'm thinking that if I use the second approach, I could look at the value of getAccuracy() from each location update and only keep the one with the highest accuracy. The downside is that if the device is moving and I keep receiving updates for a minute or so, the first location could have the highest accuracy, but since it's a minute old it's not accurate any more.
As stated above, I need just a single highly accurate location and it's okay for the app to wait 1-2 minutes for it if needed. What would be the best approach in this kind of scenario?
First, make sure the accurate location is turned on. look at Settings.Secure.LOCATION_MODE_HIGH_ACCURACY It has a noticeable advantage over only using GPS. Then listen for the location for a while and calculate the result you get to find out the best location. You can also detect if the user is moving if the number differs a lot or by using Activity Recognition API. It shouldn't be very hard to write this calculate function to get the best result.
I'm not sure about this but I really don't think waiting more than a few seconds gives you an advantage. to be sure you can simply alter this time and watch the result.
You might want to use LocationManager. In my experience FusedLocation will indeed appear to lock faster but may not be as accurate overall, or at least for a while. I have an app that also requires pretty accurate coordinates. My default is to use a LocationManager based approach but users can switch to a FusedLocation provider if they want faster locking (like when indoors).
This is a good overview https://developer.android.com/guide/topics/location/strategies
For the provider when requesting updates I'd use LocationManager.GPS_PROVIDER. It will take longer to lock since it will wait for satellites and not use Wifi or other towers. But you said that's OK. Something along these lines
LocationManager locationManager = (LocationManager) this.getSystemService(Context.LOCATION_SERVICE);
locationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, 0, 0, YourLocationListener);
Once you start getting location updates via your listener's onLocationChanged() you can start to inspect the location for accuracy, movement from last location change, etc. to try and evaluate if the GPS receiver is still settling in on a location. Once you are satisfied with the quality of the fix you can stop receiving location updates (locationManager.removeUpdates(YourLocationListener)) and then run your logic that needs the location. The link I provided has good info about this too.

Battery impact of polling for location updates less often?

I've read a lot of conflicting information on this.
Suppose I use the Fused Location API in PRIORITY_HIGH_ACCURACY mode, does it make much difference if I set the interval to, say, 10 minutes vs 1 minute? 1 hour vs 10 seconds? If so, how drastically?
I don't know how it works internally so I'm just wondering what I can do to save battery if I need high accuracy location (and relative infrequency of polling isn't an issue).
https://developer.android.com/training/monitoring-device-state/index.html
The developer site has advice on how to save battery but they don't seem to give any concrete information on exactly how much polling frequency affects battery life.
Does enabling the service keep the GPS on all the time and therefore always using battery (and so the interval would be synthetic and solely for programmatic reasons)?
Thanks!
For Fused Location API, I'm not certain if they turn off GPS or adjust reporting interval while leaving it on, but I would assume they turn off GPS between updates, or else many others would complain about power drain.
As for what Android Location Service does, they do turn off GPS and allow the phone to idle between updates if the interval is greater than 0 (check out the source in LocationManagerService). I've done quite a bit of power testing on different android phones, and found that keeping the CPU from idling can draw a noticeable amount of power. Add the power draw of GPS (which keeps the CPU from idling) and you are looking at a decent power drain (about 50% of what the screen would draw for some devices).
In the end, I'd have to agree with Gabe Sechan and advise you on choosing whether accuracy is worth the battery drain. Just ask yourself these basic questions:
Do I need to know if my user is on one side of the street or the other?
If yes, use GPS, else use Network or low accuracy location.
How often do I need to check my user's location?
If you need it about once a minute, set your interval as such. If you only care when they leave a general area, setup a geofence, or use network locations. You can also listen to location updates from other apps, and make your app smarter about when to take updates.
If I can't get my user's location within X amount of time, can I skip this update altogether?
If you can, then put a timeout feature in your update logic. If not, I strongly recommend you re-evaluate the app logic in that case.

How to get accurate position from GPS periodically

In application I need to get geo position of phone every x minutes (for now it's 5min and 50m), in such a way that phone doesn't discharge during day. The accuracy of position must be at least 40m. By now I have listeners for gps and network. The problem lies in the fact that the data I can receive sometimes is totally wrong (depends on phone) - new position can be even 200m from my real position and with 40m accuracy; next point can be the same but in opposite direction. For my app it's fatally.
So the question is next: Is there any way to get more accuracy data but not very often?
Update 1: to show the problem in action:
(The phone is lying in the fixed position)
To get more accurate location make sure you're using the ACCESS_FINE_LOCATION permission in your manifest. To prevent higher battery usage, you can use setInterval and setFastestInterval on your LocationRequest object. Longer intervals mean less battery usage by your app.
You should not be accessing the gps and network directly, you should be using LocationManager and using ACCURACY_FINE in your Criteria. This will help conserve battery life, and avoid issues with phones where the gps may have been disabled. There's more detail on that here.
As far as the accuracy of your location, you can use Location's getAccuracy method to get Android's estimate of how accurate a measurement is. If it doesn't fit your criteria, discard it and poll again.

Is location provider really a battery drain?

I need to implement location-based service. I don't need fine location, so no GPS is needed.
Easiest would be to start listening for locations updates at app start, and leave it ON:
mLocationMgr.requestLocationUpdates(LocationManager.NETWORK_PROVIDER, 10000, 100, mPendingIntent);
Since I don't need much accuracy, I set max frequency of updates, to 10s, and 100m instead of default 0, 0.
When we think location, we think battery drain, but I guess this is a shortcut and that only GPS really drains the battery. I think that such a use of network provider wouldn't drain the battery. Any thoughts?
Your 100m distance filter will do little for you from a battery drain standpoint. That will only control how many times your PendingIntent gets executed due to fixes.
Your 10 second time value might be used by the OS to control power usage, but there is no guarantee. And, with that low of a value, it seems highly unlikely that it would be used. Every hour, maybe, but not every 10 seconds.
The bigger thing is that you will be needing to keep the CPU powered on all the time. And, since you're using the PendingIntent flavor of requestLocationUpdates(), I am guessing that you plan on collecting data for a long time.
If you only have COARSE permission, Android hopefully eschews the WiFi hotspot proximity detection, which will save a bit of power.
On the whole, the network provider will consume less power than will the GPS provider. "Less" is a far cry from "little". On a Nexus-class Android device, GPS + CPU gives me a few hours battery life (as determined by using Google Navigation). I would expect network provider + CPU to last a few hours longer, but that's about it, because the CPU is a fairly significant battery drain in its own right.
My bigger concern is:
Easiest would be to start listening for locations updates at app start, and leave it ON
This sounds like you aren't actually planning on removing your location updates. This is a really bad idea, with any sort of provider (except maybe the passive provider). Please have a more concrete plan for when you are registering and removing the updates. In particular, make sure the user has the ability to control when you are consuming battery to this degree.
There is a topic about this included in the Android Developers Guide. I would recommend that you take a look at the code examples on the page.
This is what they mention regarding conserving battery and various parameters.
Adjusting the model to save battery and data exchange
As you test your application, you might find that your model for
providing good location and good performance needs some adjustment.
Here are some things you might change to find a good balance between
the two. Reduce the size of the window
A smaller window in which you listen for location updates means less
interaction with GPS and network location services, thus, preserving
battery life. But it also allows for fewer locations from which to
choose a best estimate. Set the location providers to return updates
less frequently
Reducing the rate at which new updates appear during the window can
also improve battery efficiency, but at the cost of accuracy. The
value of the trade-off depends on how your application is used. You
can reduce the rate of updates by increasing the parameters in
requestLocationUpdates() that specify the interval time and minimum
distance change. Restrict a set of providers
Depending on the environment where your application is used or the
desired level of accuracy, you might choose to use only the Network
Location Provider or only GPS, instead of both. Interacting with only
one of the services reduces battery usage at a potential cost of
accuracy.
Basically, consider reducing the frequency of the updates you request or the length of time you request them. This is like golf, the less locations you request the better. Consider the following use case:
In the example the application waits until the user performs an action that needs a location and then stops polling once the location data is no longer needed.
While polling constantly would allow the application to have a location ready at an instant notice its simply not worth the wasted resources, to mitigate the delay when requesting a location you can use getLastKnownLocation (String provider).
Edit:
There is a way to determine power usage for the various LocationProviders!
Calling getPowerRequirement () on a LocationProvider will return one of three constants.
int POWER_HIGH A constant indicating a high power requirement.
int POWER_LOW A constant indicating a low power requirement.
int POWER_MEDIUM A constant indicating a medium power requirement.
To make your code more readable look into using meetsCriteria (Criteria criteria) in any boolean checks to make your code more readable.
I would use this to determine what method your application should use for the lowest power cost, Also you have the benefit of supporting devices that have different power requirements for providers.

Does anyone know whether the Android addProximityAlert on the LocationManager is battery intensive

I just basically want to add about 20 and sometimes 80 Proximity Alerts with no time expiration with a radius of around 500 meters.
Just wondering whether by doing this will suck up the battery real quick? also would it make any difference by reducing the radius?
This will definitely eat your battery real quick. You never want to be setting more than a couple of proximity alerts in any case, the use-case you describe isn't really catered for in Proximity Alerts.
Proximity Alerts should switch between GPS and Network as required, but in my experience they tend to stick to GPS whenever it's available, and your battery will suffer as a result.
A better alternative would be to use an Alarm and a Service to check your current location against your set of 20 to 80 locations as required. This will let you manage the LBS you want to use (GPS or Cell ID), as well as the frequency of checks, all in one place. Doing it this way will let you manage your battery use much more effectively.

Categories

Resources