Look at the documentation
Answer from Andrew Brooke on Stack OverflowminDistance float: minimum distance between location updates, in meters
Videos
You are implementing LocationListener in your activity MainActivity. The call for concurrent location updates will therefor be like this:
mLocationClient.requestLocationUpdates(mLocationRequest, this);
Be sure that the LocationListener you're implementing is from the google api, that is import this:
import com.google.android.gms.location.LocationListener;
and not this:
import android.location.LocationListener;
and it should work just fine.
It's also important that the LocationClient really is connected before you do this. I suggest you don't call it in the onCreate or onStart methods, but in onResume. It is all explained quite well in the tutorial for Google Location Api: https://developer.android.com/training/location/index.html
I use this one:
LocationManager.requestLocationUpdates(String provider, long minTime, float minDistance, LocationListener listener)
For example, using a 1s interval:
locationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER,1000,0,this);
the time is in milliseconds, the distance is in meters.
This automatically calls:
public void onLocationChanged(Location location) {
//Code here, location.getAccuracy(), location.getLongitude() etc...
}
I also had these included in the script but didnt actually use them:
public void onStatusChanged(String provider, int status, Bundle extras) {}
public void onProviderEnabled(String provider) {}
public void onProviderDisabled(String provider) {}
In short:
public class GPSClass implements LocationListener {
public void onLocationChanged(Location location) {
// Called when a new location is found by the network location provider.
Log.i("Message: ","Location changed, " + location.getAccuracy() + " , " + location.getLatitude()+ "," + location.getLongitude());
}
public void onStatusChanged(String provider, int status, Bundle extras) {}
public void onProviderEnabled(String provider) {}
public void onProviderDisabled(String provider) {}
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
locationManager = (LocationManager)getSystemService(Context.LOCATION_SERVICE);
locationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER,1000,0,this);
}
}
The documentation on requestLocationUpdate() says:
The minDistance parameter can also be used to control the frequency of location updates. If it is greater than 0 then the location provider will only send your application an update when the location has changed by at least minDistance meters, AND at least minTime milliseconds have passed
So both parameters must be satisfied before you'll receive an update if you specify non-0 values.
If you set minTime to 0, it will be called once when it first receives a location update, then it won't be called until you change your position in minDistance meters.
The Documentation on requestLocationUpdate() says :
requestLocationUpdates(String provider, long minTime, float minDistance, LocationListener listener)
Register for location updates using the named provider, and a pending intent.
So you should be calling it like locationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, 3000, 10, this);
But If you set minTime to 0, it will be called once when it first receives a location update, then it won't be called until you change your position in minDistance meters.
Documentation Link for Reference
EDIT
As per the Discussion with @Matej I need to get update every 10 meters even if it happened in less than 3 seconds, and update every 3 seconds even if the location didn't change by more than 10 meters
If you want to regularly requestLocationUpdates, you should use Timer and TimerTask and have requestLocationUpdates run once every 3 seconds
schedule(TimerTask task, long delay, long period)
Schedules the specified task for repeated fixed-delay execution, beginning after the specified delay.
I read this discussion for a similar problem. I had to update location every second, but setting:
locationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, 1000, 0, this);
I didn't achieve my goal. In the official documentation I read that also if you fix a timerate for updates, it could be not keeped so rigid as setted. (I can't find anymore the developper page which talk about).
To have a fixed and sure timerate for updates I found this post.
My problem was that Location updates went to update (by observers) the activity and I got error using Timer (as suggested). the error was:
Only the original thread that created a view hierarchy can touch its views.
For anyone has similar problem I suggest to use Handler:
Handler handler = new Handler();
handler.postDelayed(new Runnable() {
@Override
public void run() {
notifyLocationObservers();
}
}, 1000);
The requestSingleLocation method new for API level 9. If you are targeting an earlier API level, this method will not be available to you.
One of the problems with obtaining location information is that it can take time to get a fix. This is more of a problem with the GPS location provider than the network provider. If you are only using the network provider, then there may not much of a delay with getting the location information when the user clicks the button (I say this knowing nothing about what your app does with the data, or what type of user experience you are trying to provide).
Something else you can try is the PASSIVE_PROVIDER. It allows you to get location updates that were requested from other apps. This will mean that you have to request the ACCESS_FINE_LOCATION permission however. You may also need to leave something running to receive the location updates (likely a service or a BroadCastReceiver). The BroadcastReceiver approach should not use that much additional battery life since it only runs when the Intent is received along with the PASSIVE_PROVIDER only getting locations when some other app requested them anyways.
The other sticky point with the PASSIVE_PROVIDER is that you should eventually call removeUpdates. Where and when to call this really depends on how your app is structured and how you handle the user exiting the app.
You can use getLastKnownLocation method, but it can be out-of-date. requestLocationUpdates is asynchronous because gps needs to "warm-up" to find new location. requestSingleUpdate method is available since api level 9, but you can implements it's using requestLocationUpdates and disabling updates after first callback to LocationListener.
It sounds like you are searching for the Critera class.
You basically define a set of criteria which then is used to get the best suitable provider for this criteria. You then pass this criteria to the getProviders() method of the LocationManager class to get the best suitable provider as a string. Be it GPS, Network etc.
You can alternatively specify the fix provider manually by doing something like this
// Get a fix from the GPS provider
LocationProvider provider = LocationManager.GPS_PROVIDER;
// Get a fix from the Network provider
LocationProvider provider = LocationManager.NETWORK_PROVIDER;
There is a very interesting read on the developers site about obtaining users location you might want to check out. Especially the part about deciding when to start listening might be of interest for you but I recommend reading the whole article.
Using the Network provider will get your best possible position without a GPS fix in other words also inside a building. You have to keep in mind tho that the position fix you obtain might be quite off of the real position when querying the network provider.
The method you are asking for requestLocationUpdates(String provider, long minTime, long minDistance, LocationListener listener) will request a location update from the set provider every minTime milliseconds or every minDistance meters and inform the listener upon that.
Hope it helps.
Did you check this site?
Specifically this link: http://developer.android.com/reference/android/location/LocationManager.html#requestLocationUpdates(java.lang.String, long, float, android.app.PendingIntent)
void requestLocationUpdates(String provider, long minTime, float minDistance, PendingIntent intent) Registers the current activity to be notified periodically by the named provider.void requestLocationUpdates(String provider, long minTime, float minDistance, LocationListener listener) Registers the current activity to be notified periodically by the named provider.void requestLocationUpdates(String provider, long minTime, float minDistance, LocationListener listener, Looper looper) Registers the current activity to be notified periodically by the named provider.
But the call you're showing uses an int as last parameter. That's not a documented function.
There are two ways of doing this:
- Use the method that you are and register a
BroadcastReceiverwhich has an intent filter which matches the Intent that is held within yourPendingIntent(2.3+) or, if you are only interested in a single location provider,requestLocationUpdates (String provider, long minTime, float minDistance, PendingIntent intent)(1.5+) instead. - Register a
LocaltionListenerusing therequestLocationUpdates (String provider, long minTime, float minDistance, LocationListener listener)method ofLocationManager.
I think that you are getting a little confused because you can handle the location update using either a BroadcastReceiver or a LocationListener - you don't need both. The method of registering for updates is very similar, but how you receive them is really very different.
A BroadcastReceiver will allow your app / service to be woken even if it is not currently running. Shutting down your service when it is not running will significantly reduce the impact that you have on your users' batteries, and minimise the chance of a Task Killer app from terminating your service.
Whereas a LocationListener will require you to keep your service running otherwise your LocationListener will die when your service shuts down. You risk Task Killer apps killing your service with extreme prejudice if you use this approach.
From your question, I suspect that you need to use the BroadcastReceiver method .
public class MobileViaNetReceiver extends BroadcastReceiver {
private static final String TAG = "MobileViaNetReceiver"; // please
@Override
public void onReceive(Context context, Intent intent) {
if ("android.intent.action.BOOT_COMPLETED".equals(intent.getAction())){
Log.i(TAG, "Boot : registered for location updates");
LocationManager lm = (LocationManager) context
.getSystemService(Context.LOCATION_SERVICE);
Intent intent = new Intent(context, this.getClass());
PendingIntent pi = PendingIntent.getBroadcast(context, 0, intent,
PendingIntent.FLAG_UPDATE_CURRENT);
lm.requestLocationUpdates(LocationManager.GPS_PROVIDER, 5000,5,pi);
} else {
String locationKey = LocationManager.KEY_LOCATION_CHANGED;
if (intent.hasExtra(locationKey)) {
Location loc = (Location) intent.getExtras().get(locationKey);
Log.i(TAG, "Location Received");
try {
DbAdapter_GPS db = new DbAdapter_GPS(context);//what's this
db.open();
String android_id = Secure.getString(
context.getContentResolver(), Secure.ANDROID_ID);
Log.i(TAG, "Android id is :" + android_id);
db.insertGPSCoordinates(android_id,
Double.toString(loc.getLatitude()),
Double.toString(loc.getLongitude()));
} catch (Exception e) { // NEVER catch generic "Exception"
Log.i(TAG, "db error catch :" + e.getMessage());
}
}
}
}
}
You are importing LocationListener from the wrong package. You seem to be importing it as:
com.google.android.gms.location.LocationListener
but the requestLocationUpdates (String provider, long minTime, float minDistance, LocationListener listener) method the last argument of this type:
android.location.LocationListener
as you can see here.
Changing the import statements to load android.location.LocationListener should fix the issue.
You should implement LocationListener for MainActivityClass and also overwrite implement methods: onLocationChanged, onStatusChanged, onProviderEnabled, onProviderDisabled.
public class MainActivity extends AppCompatActivity
implements OnMapReadyCallback, LocationListener
I got same Error and its fixed by implementing as mentioned above.
The minTime is just a hint for the LocationProvider, and it doesn't mean that your location listener will be called once every 6 seconds. You will receive more location updates, and its up to your code to pick the most accurate one.
Monitor the GPS icon on your phone. A call to requestLocationUpdates will trigger the GPS to pinpoint your location, and it will send one or more location updates to the locationlistener if it's able to get a fix. (At this point, your GPS icon should be animated as it searches for a location).
During that time, your locationlistener may receive several location updates. Your code can go and pick the most accurate location, and process only that one.
After the GPS has sent the location update(s) to your listener, there should be a period of inactivity. (your GPS icon should disappear for a couple of seconds). This period of inactivity should correspond with your minTime. The status of the GPS will also change, as it will be put into TEMPORARILY_UNAVAILABLE.
After that, the same process is repeated. (The GPS becomes AVAILABLE, and you'll again receive one or more location updates).
Also take into account, if the GPS is unable to get a location fix, the GPS icon will remain active for more then 6 seconds, but you won't be receiving location updates.
You can also monitor the status of your GPS provider through your listener, via the following method :
public void onStatusChanged(String provider, int status, Bundle extras) {}
The status is one of the following constants defined on android.location.LocationProvider
public static final int OUT_OF_SERVICE = 0;
public static final int TEMPORARILY_UNAVAILABLE = 1;
public static final int AVAILABLE = 2;
Have a look at Understanding the LocationListener in Android for an example on the minTime behavior, and a scenario (including some logging) to help you understand what's going on.
Keep in mind that tweaking the minTime and minDistance parameters on the LocationManager, and acting upon GPS status updates will allow you to fine-tune your user location development.
6000 in milliseconds equals 6 seconds, and it may seems like continiously updating. From Android dev guide "minTime under 60000ms are not recommended" Maybe it is worth to increase it to 60000ms
The documentation has a good answer.
public void requestLocationUpdates (String provider, long minTime, float minDistance, LocationListener listener)
If minDistance is greater than 0, a location will only be broadcasted if the device moves by minDistance meters. To obtain notifications as frequently as possible, set both parameters to 0.
The location change will be detected by OnLocationChange() called by the LocationListener registered at requestLocationUpdates().
To ignore the time delay in between location requests just specify it as 0. This way it is 0 seconds delay which really means no delay.
LocationManager yourLoc = (LocationManager) getSystemService(Context.LOCATION_SERVICE);
yourLoc.requestLocationUpdates(LocationManager.GPS_PROVIDER, 0, 1, onLocationChange);
The above example changes at every 1m.
public void requestLocationUpdates (String provider, long minTime, float minDistance, LocationListener listener, Looper looper)
Registers the current activity to be notified periodically by the named provider. Periodically, the supplied LocationListener will be called with the current Location or with status updates.
It may take a while to receive the most recent location. If an immediate location is required, applications may use the getLastKnownLocation(String) method.
In case the provider is disabled by the user, updates will stop, and the onProviderDisabled(String) method will be called. As soon as the provider is enabled again, the onProviderEnabled(String) method will be called and location updates will start again.
The frequency of notification 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 broadcasted 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.
The supplied Looper is used to implement the callback mechanism.
Parameters
- provider the name of the provider with which to register
- minTime the minimum time interval for notifications, in milliseconds. This field is only used as a hint to conserve power, and actual time between location updates may be greater or lesser than this value.
- minDistance the minimum distance interval for notifications, in meters
- listener a whose onLocationChanged(Location) method will be called for each location update
- looper a Looper object whose message queue will be used to implement the callback mechanism.
Throws
IllegalArgumentException if provider is null or doesn't exist
IllegalArgumentException if listener is null
IllegalArgumentException if looper is null
SecurityException if no suitable permission is present for the provider.
minTime : the minimum time interval for notifications, in milliseconds. This field is only used as a hint to conserve power, and actual time between location updates may be greater or lesser than this value.
minDistance: the minimum distance interval for notifications, in meters
You are using the wrong LocationListener class. You need to replace this:
import com.google.android.gms.location.LocationListener;
with this:
import android.location.LocationListener;
The com.google.android.gms.location stuff is for use with the FusedLocationProviderApi which is part of Google play services.
The standard Android location stuff is in android.location.
Also, you have GetCurrentLocation extends Activity. But it isn't really an Activity. You need to remove the extends Activity clause. This will then cause problems because you are calling getBaseContext() in some methods of that class. To fix this, have the constructor of GetCurrentLocation take a Context parameter and save that in a private member variable. Then use that when you need a Context instead of calling getBaseContext().
In MainActivity, when you create a new GetCurrentLocation, you can do this:
LocationListener locationListener = new GetCurrentLocation(this);
passing this as the Context parameter (Activity extends Context).
The error telling you that there is no overload method requestLocationUpdates that accepts parameters (String,int,int,com.google.android.gms.location.LocationListener)
The closer method is
requestLocationUpdates(String provider, long minTime, float minDistance,
LocationListener listener);
So possible solution to fix your error is:
long t = 5000;
float d = 10;
locationManager.requestLocationUpdates(
LocationManager.GPS_PROVIDER, t, d, locationListener);
Refer Android LocationManager for more details