In my application, I have calculated speed based on GPS locations.
As GPS receiver can have different coordinates even being on the same location, my app is recording speed even when phone is on my desk.
I need to avoid GPS data if I am receiving it being on same location.
I am thinking of adding some logic based on “bearing”, so that I can decide if the phone is actually moving or it’s receiving jumpy location data from any direction.
Before that I would like to know is there any other way to avoid this kind of data?
AS per the Javadoc for the method request public void requestLocationUpdates (long minTime, float minDistance, Criteria criteria, PendingIntent intent) found here
minTime minimum time interval between location updates, in
milliseconds minDistance
minimum distance between location updates, in
meters
so you can use minDistance parameter to avoid getting update for very short distances...
After working on many methods I programmed it with bearing.
I am getting speed based on last 5 locations. I added Logic to check bearing for each location with next location and if all bearing have larger difference, I assumed locations are being received from random directions and so the device is not actually moving.
And it worked great for me :)
Related
I have used onLocationChanged method of LocationListener for detecting change in location of my device. In requestLocationUpdates method I have set minimum Time = 5 seconds and minimum Distance = 2 meters, but requestLocationUpdates method is giving me updates even when my device is not moved at all (placed stationary). So please tell what is the issue with my code?
This my code:
public class LocationDetector implements LocationListener {
#Override
public void onLocationChanged(Location location) {
Log.d("GPS: ",location.getLatitude()+", "+location.getLongitude());
}
.
LocationManager manager = (LocationManager)getSystemService(Context.LOCATION_SERVICE);
.
manager.requestLocationUpdates("gps", 5000, 2, new LocationDetector());
The GPS location can fluctuate. If you actually log the locations that you receive, you'll probably see that the location actually changes by 2 meters or more whenever a location update comes.
Edit: Ideas for dealing with the fluctuation added:
How to deal with GPS fluctuation depends on your application's needs. Some possible ideas include:
If you don't need a really accurate location, then use a higher distance limit in the requestLocationUpdates() call to not receive updates for very small location changes. You can think what's the absolutely necessary accuracy required by your use case and then use the highest possible distance limit.
If you don't expect the location to change very quickly or you don't need to react to location changes very quickly, then use a higher time limit in the requestLocationUpdates() call. This also makes sense if you have some very heavy code triggered by onLocationChanged() like if you always fetch some data over the network (reverse geocoding etc.).
The time limit also has more impact on the battery usage. Android documentation says:
...it is more difficult for location providers to save power using the
minDistance parameter, so minTime should be the primary tool to
conserving battery life.
If you really need an accurate location then there are some ways to decrease the fluctuation.
First of all the Location object received in onLocationChanged() usually has an estimated accuracy available by calling the Location.getAccuracy() method. You can simply ignore any location updates that have very poor accuracy (compared to the accuracies of previous location updates).
You can also do some filtering if you have a short buffer of the most recent locations. Calculating an average will reduce the amount of sudden changes but it also increases the response time. That is: a rapid change in the location will completely show up in the averaged location data only after some time. (Of course the averaged data starts to move towards the location right away, but it takes a while.) Also it will "let the spikes trough" to some amount.
If a fast response time is important and any major "spikes" in the data should be eliminated, then calculating the median is a better option. It will not smooth out the small changes in the data that much, but random spikes can be filtered out. If there's a real (permanent) sudden change in location, then the median filtering reacts to that with only a very small delay.
(These things are easy to try out in your favourite spreadsheet application.)
I know with the Android and the Location API's it's possible to receive periodic updates of latitude and longitude through an interval of time using the "setInterval" method and other methods on the "LocationRequest" class, but what I'm wondering is, what would be a good way to get latitude and longitude updates via GPS based off of a change in distance compared to the previous location without having it on all the time and not wasting battery (preferably a solution that is energy efficient).
For example, say I start at one place and then 2 minutes later I'm 5km from the distance that I originally started at. At this point the GPS would detect the change in location and update the latitude and longitude on the device.
If anyone could provide some insight or code samples on how to do this, that'd be great!
Thanks
You can based your position attribute update on how far you are from the previous location, but you can't based GPS frequency update on that, simply because you need a location request to find out that you are far enough.
If you want an energy efficient solution, you can reduce the rate at which new update appear. You can also reduce the window duration in which you listen for position (position may be less accurate).
A lot of information can be found here, specially in Adjusting the model to save battery and data exchange and Deciding when to start listening for updates chapters
You can get the location change if you specify the distance you want to get updates in the requestLocationUpdate parameter.
public void requestLocationUpdates (String provider, long minTime, float minDistance, LocationListener listener)
Here is example:
LocationManager yourLoc = (LocationManager) getSystemService(Context.LOCATION_SERVICE);
yourLoc.requestLocationUpdates(LocationManager.GPS_PROVIDER, 0, 2, onLocationChange);
Here you will receive location changes after every 2 meters you have travelled, irrespective of the time you spent at a particular location.
Hope that answers your question!!!
I made a simple GPS. app. for android, storing the route coordinates into file.
I'm confused, I got more onLocationChanged event when I stand in one place. The bearing and speed was zero of course in the Location when the event comes, but it Is interested, because I used 1 meter for minDistance when I registered the LocationListener. (the minTime was zero)
Are you sure that the values returned by getLatitude and getLongitude are identical to their previous values? Normal GPS is only accurate to within a meter or two, so it seems to me that random shifting of your location as perceived by your GPS sensor could be the problem.
You may be registering with more GPS satellites as your app runs and this may shift your position and reduce the error in all the times received from all the gps signals. Also, as you stand still position will become more and more accurate it is possible to get a gps signal accuracy down to cms see: http://atarist.home.xs4all.nl/geo/gps_accuracy.htm and wiki link on real time kinematic especially if you get a connection to a reference signal
When getting GPS location on a fixed interval (say per hour), does this drain the battery every hour, every minute or only when either actually getting the location each hour or updating the location. I'm eager to know what goes on in the background.
Here is what this reference says
"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. "
So I'm hoping that when the location is changed, or after minTime, the GPS radios are on, and after getting location, the GPS radios are off
Can anyone confirm this to be true?
According to reference we can decide that expensive battery using happens when GPS engine try to get new location and we can control freqency of this using method public void requestLocationUpdates (long minTime, float minDistance, Criteria criteria, PendingIntent intent)
Battery consumed is at its peak at the time when location manager tries to pinpoint your location(you can observe GPS icon blinking on status bar at that time) and this happens once in an hour in your case.. So GPS is automatically turned to "not available" state once you get a location until your next hour is reached..
And the line "In particular, values under 60000ms are not recommended" is said because it takes some time for GPS to point out your location, typically a minute maybe depending on your satellite strength.. So if your minTime is set to less than a minute(60000ms) its like your GPS is almost on for all the time..
Read here for more details
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.