There's two ways to trigger the update, Time and Distance, when you set the Interval (is the slowest time constant for the update), FastestInterval (is the minimum time to update) and setSmallestDisplacement is the minimum distance (in meters) for the update.
Even if you still in the same place, the location may change depending on your accuracy and that will trigger the onLocationChange
Answer from Lucas Queiroz Ribeiro on Stack OverflowUsing the Fused Location API you can do something like:
mLocationRequest = LocationRequest.create()
.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY)
.setInterval(INTERVAL)
.setFastestInterval(FASTEST_INTERVAL);
Then when an event is triggered in your app and you want to change the intervals, you would call the same piece of code but just change the INTERVAL and FASTEST_INTERVAL values.
After you change them do no forget to update the Location Updates like so:
LocationServices.FusedLocationApi.requestLocationUpdates(mGoogleApiClient, mLocationRequest, this);
Use removeLocationUpdates before changing the interval with addOnCompleteListener to make sure you unregistered the previous request, and re-init the LocationRequest object:
LocationServices.FusedLocationApi.removeLocationUpdates(mLocationCallback).addOnCompleteListener(new OnCompleteListener<Void>() {
@Override
public void onComplete(@NonNull Task<Void> task) {
mLocationRequest = new LocationRequest();
mLocationRequest.setInterval(5000);
LocationServices.FusedLocationApi.requestLocationUpdates(mGoogleApiClient, mLocationRequest, this);
}
});
Based on the relevant Android documentation:
setInterval(long)means - set the interval in which you want to get locations.setFastestInterval(long)means - if a location is available sooner you can get it (i.e. another app is using the location services).
For example, you start your application and register it via setInterval(60*1000), that means that you'll get updates every 60 seconds.
Now you call setFastestInterval(10*1000). If you are the only app which use the location services you will continue to receive updates approximately every 60 seconds. If another app is using the location services with a higher rate of updates, you will get more location updates (but no more frequently that every 10 seconds).
I believe that it has a good impact on battery life consumed by your app, you define the maximum amount of time that you can wait while saying that if an update is available, you want it. The battery consumption will be credited to the app which requested the more frequent updates and not yours.
Also: Is there an inbuilt function to check the location updates only if the distances of the first update are more than 20meters with the second update?
LocationRequest has a method you can use to set the minimum distance between updates.
int minimumDistanceBetweenUpdates = 20;
LocationRequest request = new LocationRequest();
request.setMinimumDisplacement(minimumDistanceBetweenUpdates);
// ... request.setInterval(interval); etc
You are not supposed to call mLocationClient.requestLocationUpdates(mLocationRequest, this); inside onLocationChanged(Location location)
since you are registering the listener again, and you will get the first call immediately.
so what i would do would be:
- dont call
mLocationClient.requestLocationUpdates(mLocationRequest, this);and see if anywaysmLocationRequest.setInterval(1000);is taking effect if this doesnt work, try to unregister the listener, and then use a trick to wait before registering it again with the new settings, something like:
Handler h = new Handler(); @Override public void onLocationChanged(Location location) { //... all your code mLocationRequest.setInterval(1000); mLocationClient.removeLocationUpdates(LocationListener listener) h.postDelayed (new Runnable(){ public void run(){ mLocationClient.requestLocationUpdates(mLocationRequest, YOUROUTTERCLASS.this); } }, 1000); }So during one second there is not registered listener, so you wont get any updated, and after that, the listener is registerered with that interval.
Try using mLocationRequest.setFastestInterval(long millis)
As mentioned in developer.android.com :
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.
Since it seems to be a real problem in Android, a workaround could be a Handler to remove location updates manually.
listHandler = new Handler() {
public void handleMessage(Message msg) {
if (msg.what == 0) {
mLocationClient.removeLocationUpdates(MyActivity.this);
//Location Updates are now removed
}
super.handleMessage(msg);
}
};
After you request for location updates (for a maximum duration of 10s) you call this Handler, of course delayed for 10s.
myLocationClient.requestLocationUpdates(...);
listHandler.sendEmptyMessageDelayed(0, 10000);
This makes sure, that after 10s your location updates are removed.
In the documentation (https://developer.android.com/reference/com/google/android/gms/location/LocationRequest.html#setExpirationDuration(long))
It says that: "The duration begins immediately (and not when the request is passed to the location client), so call this method again if the request is re-used at a later time."
One would expect this duration to start when following line is called:
LocationServices.FusedLocationApi.requestLocationUpdates(googleApiClient, request, this);
But, documentation states this duration begins when request object is created.
Currently you can't get updates faster than once per second. This is the hardware gps limit. Network location is a bit slower (used when indoors) - currently about once every 5 seconds. Raw accelerometer data comes in at a higher frequency, but tends to be very noisy when integrated directly. This may improve in the future, but probably not at the high frequency you're looking for.
I am trying to change with below parameter and its working for me with whatever I set.
locationRequest.setFastestInterval(10000); // Every 10 sec it gives lat/lng
Please try with in your side with same change.