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.
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.
I would implement in my app GPS, I would know user position every 1 minute and I am not sure how could I do it preserving battery. Should I destroy "requestLocationUpdates" every time I get location and after a minute call it again ? Are there better way?
First Solution
If you check the documentation of LocationManager (Link below) you would see that it takes an argument minTime which indicates the minimum time interval between location updates, in milliseconds.
If you want an update every 1 minute, then set this argument to 60*1000.
However prior to JellyBean, minTime is not effective.
Link:
http://developer.android.com/reference/android/location/LocationManager.html#requestLocationUpdates(java.lang.String, long, float, android.location.LocationListener)
Second Solution
A second solution which I recommend is to use a Handler and a Looper. Basically every certain amount of time X you request a Location update then you cancel the location update until you request it again after X time, and it loops again. Check the answer of this question Android Location Listener call very often
If you know the user location every minute then:-
Yes you should destroy "requestLocationUpdates" and implement an AlarmManager which will requestUpdate for Location
I developed an application that fetches GPS location. I specified minTime as 20 seconds and minDistance as 1 meter in requestLocationUpdate method. But still i am getting location in 2-3 seconds interval and sometimes it takes more than one minute. Can i get location at particular time interval and within 1 minute?
Please Help.
Thanks in advance.
Can i get location at particular time interval and within 1 minute?
Not necessarily.
First, you set minDistance to 1 meter. Try using 0.
Second, you are limited by how frequently the GPS radio actually gets fixes, which will be based on environmental factors and is outside of your control.
Third, minTime is a hint, as the documentation explains. Hence, you may get fixes more frequently than it, or less frequently. For a minTime of 20 seconds, it is unlikely that Android will power down the GPS radio between fixes, and so I suspect that value is not helping you any.
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.
LocationManager#requestLocationUpdates allows you to pass in a minTime and minDistance parameter. I'm having a hard time deciding what these numbers should be, and could appreciate some guidance.
Our app is not a turn-by-turn navigation app; I just want to show the 10 nearest points of interest. Since I'm showing the 10 nearest, they can get a little stale, but if the user is in a moving vehicle, I'd want/need to update them pretty frequently to avoid staleness.
I imagine a lot of people are in the same position of vague requirements: "I don't want the data to be too stale, but I don't want to waste battery." How can I turn these vague requirements into concrete numbers?
***<Edit>***
As of JellyBean, the criteria is (minTime & minDistance), so it has
to satisfy both to return a location.
***</Edit>***
Based on your problem, it sounds to me like the minTime parameter is irrelevant.
What you really need to worry about is minDistance, so that if a user is in a fast moving vehicle, it will keep up.
If a person is driving 60 MPH, they move about 27 meters per second.
Considering this critera... I would say to use:
minTime = 60000 // update every 60 seconds
minDistance = 90 // in a fast moving vehicle, it will update roughly once every 3 seconds
It has been described nicely in requestLocationUpdates docs
The frequency of notification or new
locations may be controlled using the
minTime and minDistance parameters. If
minTime is greater than 0, the
LocationManager could potentially rest
for minTime milliseconds between
location updates to conserve power. If
minDistance is greater than 0, a
location will only be broadcast if the
device moves by minDistance meters. To
obtain notifications as frequently as
possible, set both parameters to 0.
Background services should be careful
about setting a sufficiently high
minTime so that the device doesn't
consume too much power by keeping the
GPS or wireless radios on all the
time. In particular, values under
60000ms are not recommended.
I can suggest a better idea that, initially request updates with a little larger interval and get the locations. Now check if the distance between the consecutive locations is more than the minimum distance to distinguish the nearer locations, change your request update interval to lower value. Similarly if in this lower interval the distance you computed of much lower that indicates the user in not traveling through vehicle then update interval to larger value.
To update the interval you have to unregister previous listener and then re-regiser with new value.
For your problem at hand, do take a look at the PASSIVE_PROVIDER. Basically it will help you get updates when any other apps might request for them. So, you can use this in conjunction with other provider.