I am currently trying to work with Google Play Location Updates for an Android project.
I have set the updateInterval for LocationRequests at 5000 (5 seconds) and fastestInvertval also at 5000:
mLocationRequest = new LocationRequest();
mLocationRequest.setInterval(5000);
mLocationRequest.setFastestInterval(5000);
I am now thinking of getting rid of old code that dealt with time-stamps and calculating speed through getting the difference between the two times. I've been hesitant to do so because I though that maybe the updateInterval for the LocationRequests would be inaccurate, and would have large margins of error.
My question is:
Is LocationRequests' Update Interval accurate so that I could remove safeguards such as the time stamps? If so, what is the approximate margin of error?
No. The updateInterval is the fastest it will return a new value. It could be close. It could take twice that. It could take 100 times that. It could take 8 hours, if someone went inside. Also very few GPS chips are going to give a new result more than once every 30 seconds, at least as of the last time I checked. In short, use timestamps.
The location updates may be faster than this rate if another app is receiving updates at a faster rate, or slower than this rate, or there may be no updates at all (if the device has no connectivity, for example)(source).
It all depends on the level of accuracy that you need, some samples might come several seconds late. You would have to see if for your application this is acceptable or not. You can always retrieve the timestamp of your location sample from the location.getTime() method if you need to check.
Related
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.
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'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.
This is a very strange behaviour. If I have something like this (time interval set to 30 minutes):
mLocationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER,30 * 60 * 1000,100,mLocationListener);
My first fix takes forever and sometimes I don't get it at all (I waited for about 20 minutes) However if I choose a smaller interval for the time (30 seconds) I get it right away.
I thought that the values minTime and minDistance are only for getting new consecutive updates, and it wouldn't affect the first fix. I should get the first fix as soon as it's available. Am I doing something wrong?
Thanks
I'd suggest to use two locationManagers, one as you are already doing for long-term updates, and another to get the first fix. Then you can unregister the second one as soon as you get the callback from it.
I heard of this pattern from Reto Meier and it's called "back-off" location. We are using it in mixare with the coarse location manager to get the first fix, and the GPS to get more precise infos. You can check the code here: https://github.com/mixare/mixare/blob/master/src/org/mixare/MixContext.java starting at line 150 (more or less)
HTH,
Daniele
You may check, if well-known 3rd party GPS tools (like GPS Status) have problems as well, or there is something with your code.
Please keep in mind that satellite visibility -- and therefore GPS signal quality -- may change quickly and first fix in a few days may take substantially longer than usual.