I'm trying to find a way to improve the accuracy obtained from Google Play Services's Fused Location Provider.
I'm testing an app that uses LocationServices and allows the user to choose from a set of update frequencies (every 30 seconds, every min, every 5 min, every 10 min). It then requests location updates from the fused location provider with the chosen interval, with a priority of PRIORITY_HIGH_ACCURACY.
It works, but the locations obtained don't seem to be as accurate as they could be. The accuracy values are typically more than 10 meters, while a third party GPS app (such as GPS test) typically reaches better accuracy if I wait long enough.
The Android documentation has the following to say:
The priority of PRIORITY_HIGH_ACCURACY, combined with the ACCESS_FINE_LOCATION permission setting that you've defined in the app manifest, and a fast update interval of 5000 milliseconds (5 seconds), causes the fused location provider to return location updates that are accurate to within a few feet. This approach is appropriate for mapping apps that display the location in real time.
Indeed, when I choose a very small frequency (such as 5 seconds or 2 seconds), I notice an overall improvement in the accuracy of the obtained locations - they sometimes get as good as 3-4 meters. However, it looks like choosing larger update intervals result in lower accuracy.
So I'm thinking of the following strategy: schedule a task that, at the interval chosen by the user: (1) starts requesting location updates every few seconds (2 seconds), (2) waits for 20 seconds, then (3) stop requesting updates.
I tried to use a Handler in foreground service to accomplish that. It works when the screen is on, but, as soon as the screen is turned off, the scheduling becomes seemingly unpredictable. So it looks like I'll have to resort to something like AlarmManager to schedule this task. This answer suggests a similar approach: https://stackoverflow.com/a/26298509/1131904 ; I also found this article, which tackles the similar problem of how to schedule periodic tasks in a battery efficient way: https://wangjingke.com/2016/09/23/Multiple-ways-to-schedule-repeated-tasks-in-android
Has anyone else run into a similar problem? Is using AlarmManager a good approach?
To answer you first question, we have made the some observation. In general, the occurrence of high-accuracy locations (3-10 m) decreases with increasing interval. However, the exact behavior seems to differ between vendors. On Samsung S9 and S8, the threshold appeared to be at 10 seconds. Above this interval, high-accuracy locations were very rare. On other devices (Pixel 3a, Xiaomi MI 8, OnePlus 6T) high-accuracy locations were still frequent at an interval of 30 seconds. All observations were made under open sky.
Related
Android 8 only allows background location updates a few times per hour. This isn't a problem since I only request them about once an hour and only if the device isn't STILL and there arn't already passive updates doing the job. So maybe a few times a day. No detectable battery use on Android 7.
However, I do have an accuracy requirement and I discard locations with horizontal accuracy worse than about 1000 feet (Basically cell tower locations). The problem is that the network location comes almost instantly, and then the app is throttled and never receives the next update which might come from the GPS. Typically I would wait a minute to get a location with the desired accuarcy and then give up. On Android 8, even if I wait an hour I just get the network location every 20 minutes or so because of the throttling.
I can't find any LocationRequest setting for miniumum accuracy which would solve the problem entirely. PRIORITY_HIGH_ACCURACY absolutley does NOT do this. It is only a "hint". setSmallestDisplacement() doesn't help because it doesn't affect the first update. Batching updates helps on rare occasions in my testing but not with any reliability.
Further, waiting in PRIORITY_HIGH_ACCURACY for any length of time is not reasonable from a user perspective since the location indicator will be active on the device the whole time, even if the app is being throttled.
Does anyone have suggestions on how I could solve this problem? Perhaps Android does not intend for PRIORITY_HIGH_ACCURACY to be used in the background at all, although I can find nothing about this in the documentation.
If you need GPS, just use the GPS provider. Don't screw around with the Criteria, request what you really need.
I'm using Fused Location Provider library in android. It is working perfectly fine. But I've an issue with it, it returns location updates in 5 sec minimum.
I've tried every thing like setting minimum updates time to 1 millisecond, and distance to 0.01 meter and Priority to PRIORITY_HIGH_ACCURACY
My code :
locationrequest.setInterval(1); // 1 milliseconds
locationrequest.setSmallestDisplacement(0.01f); // 0.01 meters locationrequest.setPriority(LocationRequest.PRIORITY_BALANCED_POWER_ACCURACY);
But no use, still minimum time between two successive location updates is 5 seconds.
My Questions is : Is there any way to decrease location updates time to 5 milliSeconds ?
-> I need location updates for only 10 minutes, So no issue with the high battery consumption.
-> I need any way (possible): Is there any external hardware available, which connects via Bluetooth and send location updates upto that level ?
Edits:
Let me ask you a different question :
What can be the minimum possible time for location updates and how to achieve that ?
Let's say i want to track a car, which is moving with the speed of 400 KM/h, means 5 meter in about 50ms. So can you suggest any better way to track this car ?
The precision and accuracy of location-sensing hardware (GPS, AGPS, etc.) means that getting updates more frequently than every few seconds isn't likely to provide meaningful results. In fact, technology like the Fused Location Provider is likely to prioritize getting more accurate results rather than providing results every few hundred milliseconds.
In addition to that, the battery drain from getting updates multiple times a second is likely to be very significant.
All that said. The way to get every update that your location-sensing hardware is receiving is to set the location update interval and minimum displacement to zero, and to prioritize accuracy.
locationrequest.setInterval(0); // No delay.
// locationrequest.setSmallestDisplacement(0); // This is the default.
locationrequest.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY);
Note that this will give you every update, but depending on the hardware limitations, and potentially the Fused Location Provider implementation, there's no guarantee this will be any faster than the 5s frequency you've found so far.
I got to program Android from other platforms I used with GPS . on the other platfroms I had access to the GPS HW (I had a low level GPS driver) and by that I could get GPS updates 5 times per second and even more
Now I work with Samsung Galaxy S2 (which it is clear to me that its GPS is very strong and can supply several updates per second
Currently when I set the GPS provider to supply updates in minimum distance and minimum time like this:
mlocManager.requestLocationUpdates(
LocationManager.GPS_PROVIDER, 0, 0, mlocListener
);
I get 1 update per second (or 800ms as smallest gap between two updates) which is too low for my application. Is there a way to force the GPS HW to report more updates somehow ? I guess it is not exposed to the user but is there still some way to access the registers of the GPS HW somehow ?
Currently you can't get updates faster than once per second in most of the phone.This is the hardware gps limit.
Usually in most of the phones,it is at 1hz.
It all depends on hardware and scenario where you are using ( Indoor,Outdoor)
But again, You could check using
LocationRequest setFastestInterval (long millis)
This allows your application to passively acquire locations at a rate faster than it actively acquires locations, saving power.
Unlike setInterval(long), this parameter is exact. Your application will never receive updates faster than this value.
This method sets the fastest rate in milliseconds at which your app can handle location updates. You need to set this rate because other apps also affect the rate at which updates are sent. Location Services sends out updates at the fastest rate that any app requested by calling LocationRequest.setInterval().
If this rate is faster than your app can handle, you may encounter problems with UI flicker or data overflow.
I'm creating an application (For educational purposes) which records the user's location every 30 minutes, and enables the user the view all the locations on the map. I don't want updates to be more frequent than 30 minutes, but they are.
This is how I call requestLocationUpdates:
locationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, 30 * 60 * 1000, 0, pe);
Now, the documentation clearly says:
The elapsed time between location updates will never be less than minTime
But I did see some answers here on SO stating differently (This answer, for example).
It seems like I'm getting updates whenever they are available from the GPS. The GPS icon never turns off and the updates rate becomes greater than 1 update/second. So I have 2 questions here:
The minTime parameter doesn't fulfill its purpose, not even as a hint (Yea, a hint to 30 minutes update rate leads to more than update a second...). What does it do, then?
Is there any other way to do it? I don't want the GPS to be enabled all the time because it will consume my battery too fast. Maybe I could schedule alarms repeating each 30 minutes, and call requestSingleUpdate?
The minTime parameter doesn't fulfill its purpose, not even as a hint (Yea, a hint to 30 minutes update rate leads to more than update a second...). What does it do, then?
From Jellybean onwards devices must observe the minTime parameter, so it does have a purpose (now).
Is there any other way to do it? I don't want the GPS to be enabled all the time because it will consume my battery too fast. Maybe I could schedule alarms repeating each 30 minutes, and call requestSingleUpdate?
Yes, use a Handler to request one update with requestSingleUpdate() every 30 minutes.
I've tackled this before in a previous question, let me know if the code in that answer helps and if you have any questions it doesn't address.
The second parameter, min distance difference in meters is set to zero, it causes constant updates.
Prefer using requestSingleUpdate within a timer+handler on a desired period in minutes.
I am experimenting with Androids location updates. The requestLocationUpdates is responsible for providing the updates. With the following code:
locationManager.requestLocationUpdates(provider, 300000, 10, this);
I am only supposed to receive updates 5 minutes and 10 meters apart. But the updates just keep coming in seconds apart and even when I am sitting still.
GPS is the provider I am using.
I need to space the updates out. What can I try?
The 10m is too small - I would increase that. GPS accuracy isn't great, and so every time it senses a small difference you will get another location. I'd bump it up to 100m and I expect you will then get a sensible number of locations coming through.
If you do want it more specific, then you'll need to handle the volume as more accurate means more volume.
Hers what i'd do:
First of all I check what providers are enabled. Some may be disabled on the device, some may be disabled in application manifest.
If any provider is available I start location listeners and timeout timer. It's 20 seconds in my example, may not be enough for GPS so you can enlarge it.
If I get update from location listener I use the provided value. I stop listeners and timer.
If I don't get any updates and timer elapses I have to use last known values.
I grab last known values from available providers and choose the most recent of them.
The 10m is too small for a GPS reading, try 100m. You'll also have issues with power saving mode, and app battery optimisation on most Android phones.
Android 10 and above has very strict background location updates, and may kill apps that run in the background. Later versions will also remove apps that have not be used recently.