Can I use the same locationManager for requesting updates for the gps and network provider, or should I create two locationManagers and separate onLocation changed functions etc. I got really confused about this
You will want to check and see which one is available in the order you want to use them and then use the corresponding one:
if(mLocationManager.isProviderEnabled(LocationManager.GPS_PROVIDER)){
mLocationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, LOCATION_UPDATE_MIN_TIME, LOCATION_UPDATE_MIN_DISTANCE, locationListener);
}
else if(mLocationManager.isProviderEnabled(LocationManager.NETWORK_PROVIDER)){
mLocationManager.requestLocationUpdates(LocationManager.NETWORK_PROVIDER, LOCATION_UPDATE_MIN_TIME, LOCATION_UPDATE_MIN_DISTANCE, locationListener);
}
You can use the same listener because all the listener's methods take as a parameter a Location object which is source agnostic:
#Override
public void onLocationChanged(Location location) {
// updateLocation();
}
Related
I have been trying to find the location obtained by GPS_Provider and Network_Provider for every 5 minutes and at the same time stamp for the two values obtained at any specific time.
I tried using the following location strategy given
LocationManager locationManager = (LocationManager) this.getSystemService(Context.LOCATION_SERVICE);
// Define a listener that responds to location updates
LocationListener locationListener = new LocationListener() {
public void onLocationChanged(Location location) {
// Called when a new location is found by the network location provider.
makeUseOfNewLocation(location);
}
public void onStatusChanged(String provider, int status, Bundle extras) {}
public void onProviderEnabled(String provider) {}
public void onProviderDisabled(String provider) {}
};
// Register the listener with the Location Manager to receive location updates
locationManager.requestLocationUpdates(LocationManager.NETWORK_PROVIDER, 300000, 0, locationListener)
locationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER,300000, 0, locationListener)
But here the Location Manager will call the onLocationChanged() method of the listener if the time since last location update is greater than the notificationInterval.
This brings me some time stamp difference between values generated by GPS_Provider and Network_Provider after every 5 minutes.Is there any way such that I can find the location that GPS_Provider and Network_Provider generate at a same time stamp.
Example:
Now: GPS_Provider(lat,long) at 09:35:12 , Network_Provider(lat,long) at 09:35:14
I need: GPS_Provider(lat,long) at 09:35:12 , Network_Provider(lat,long) at 09:35:12
In short, no.
The location api doesn't work in a synchronous way, meaning you have no guarantee when exactly you'll get the update. the time frames which you supply state the maximum interval between updates.
Having said that, you could start the updates with lower interval (such as 50ms) and get a bunch of updates, sort them by the second of the timestamp and get the ones which have the same value.
Update
You can use the getLastKnownLocation method to get the last location known by the provider, check the docs here.
When I open my app and press a button I want it to request a single location solely from the GPS to get the most accurate location possible. I did the following:
LocationManager mlocManager = (LocationManager)GetActivity().getSystemService(Context.LOCATION_SERVICE);
if (mlocManager.isProviderEnabled(LocationManager.GPS_PROVIDER)) {
LocationListener mlocListener = new LocationManagerHelper(...);
Criteria criteria = new Criteria();
criteria.setAccuracy(Criteria.ACCURACY_FINE);//accuracy fine calls accuracy high
mlocManager.requestSingleUpdate(criteria,mlocListener,null);
}
When I open the GPS inside my house, go to the window and !only then! I press that button, I get a location far from me with the accuracy of 300-900! I thought that maybe a second request will improve it but even 4-5 requests remains on the same spot with the same low accuracy, also, the other requests are very fast as if it didn't really ask the GPS again for a location but took it from the cache of some sort.
If I open the GPS while I'm already near the window, the location is better and sometimes I get to accuracy of 20-30, the thing is, that even then, sometimes the accuracy is not that high so I was wondering how can I initialize the GPS/location so if I get a bad accuracy in the first try, at least it will give me a better one on the second try.
Thanks
It sounds like the LocationManager is using cached data like you suggest.
You could try using the requestLocationUpdates() method on LocationManager instead. If you just require the one location fix, then disable the locationUpdates by calling the removeUpdates() method
after first callback to LocationListener.
This approach will also allow you to wait for a location that has sufficient accuracy. The following code shows how to filter locations if the accuracy is too low for your needs.
LocationListener locationListener = new LocationListener() {
public void onLocationChanged(Location location) {
if (location.getAccuracy() > THRESHOLD) {
return;
}
//Act on location data here
//Then remove the updates once done
mlocManager.removeUpdates(mlocListener);
}
public void onProviderDisabled(String provider) {}
public void onProviderEnabled(String provider) {}
public void onStatusChanged(String provider, int status, Bundle extras) {}
};
I want to know if a Certain Provider is Disabled will the LocationManager stop listening to the location changes for that provider ? If not then how can i manually stop listening for updates for that provider. Thanks In Advance
Your location listeners will not stop until you call myLocationManager.removeUpdates(myListener);. Check my answer to a different question [here] to know what else you need to do for connection status updates1.
give this a whirl
myLocationManager = (LocationManager)this.getSystemService(LOCATION_SERVICE);
myListener = new LocationListener() {
public void onLocationChanged(Location location) {
Log.i("LocationListener", "Logging Change");
}
}
myLocationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER,
5000, 1, myListener);
myLocationManager.removeUpdates(myListener);
I have a general question about LocationListener in Android. Perhaps this is about Android or Java events in general, but not sure.
There seems to be a million ways to set up a LocationListener, and they all seem pretty ugly (mainly because of lack of reusability). Here is an example from android found here:
// Acquire a reference to the system Location Manager
LocationManager locationManager = (LocationManager) this.getSystemService(Context.LOCATION_SERVICE);
// Define a listener that responds to location updates
LocationListener locationListener = new LocationListener() {
public void onLocationChanged(Location location) {
// Called when a new location is found by the network location provider.
makeUseOfNewLocation(location);
}
public void onStatusChanged(String provider, int status, Bundle extras) {}
public void onProviderEnabled(String provider) {}
public void onProviderDisabled(String provider) {}
};
// Register the listener with the Location Manager to receive location updates
locationManager.requestLocationUpdates(LocationManager.NETWORK_PROVIDER, 0, 0, locationListener);
This works, but, I'm really surprised that this is a standard way of writing OOP code...
What I would really like to see is a simple a reusable way to implement LocationListener. Anybody know of a simple tutorial on how this could be done? My goal would be to be able to implement this easily any Activities that need to be updated with gps information... perhaps a Service? Thanks!
My app checks at a specific time whether a user is at a given location. I use the alarm manager to start a service that makes this call:
locationManager.requestLocationUpdates(bestProvider, 0, 0, listener);
And also checks:
locationManager.getLastKnownLocation(bestProvider);
But I'm having problems when running on a real device. For one thing, getLastKnownLocation is most likely the last place the GPS was on, which could be anywhere (i.e., it could be miles from the user's current location). So I'll just wait for requestLocationUpdates callbacks, and if they aren't there within two minutes, remove the listener and give up, right?
Wrong, because if the user's location is already stable (i.e., they've used GPS recently and haven't moved) then my listener will never be called because the location doesn't change. But the GPS will run until my listener is removed, draining the battery...
What is the right way to get the current location without mistaking an old location for the current location? I don't mind waiting a few minutes.
EDIT: It's possible that I'm wrong about the listener not being called, it may just take a little longer than I thought... Hard to say. I'd appreciate a definitive answer still.
The code may be something like that:
public class MyLocation {
Timer timer1;
LocationManager lm;
public boolean getLocation(Context context)
{
lm = (LocationManager) context.getSystemService(Context.LOCATION_SERVICE);
lm.requestLocationUpdates(LocationManager.GPS_PROVIDER, 0, 0, locationListenerGps);
timer1=new Timer();
timer1.schedule(new GetLastLocation(), 20000);
return true;
}
LocationListener locationListenerGps = new LocationListener() {
public void onLocationChanged(Location location) {
timer1.cancel();
lm.removeUpdates(this);
//use location as it is the latest value
}
public void onProviderDisabled(String provider) {}
public void onProviderEnabled(String provider) {}
public void onStatusChanged(String provider, int status, Bundle extras) {}
};
class GetLastLocation extends TimerTask {
#Override
public void run() {
lm.removeUpdates(locationListenerGps);
Location location=lm.getLastKnownLocation(LocationManager.NETWORK_PROVIDER);
//use location as we have not received the new value from listener
}
}
}
We start the listener and wait for update for some time (20 seconds in my example). If we receive update during this time we use it. If we don't receive an update during this time we use getLastKnownLocation value and stop the listener.
You can see my complete code here What is the simplest and most robust way to get the user's current location on Android?
EDIT (by asker): This is most of the answer, but my final solution uses a Handler instead of a Timer.
If the user's location is already stable, then getLastKnownLocation will return the current location. I'd call getLastKnownLocation first, look at the timestamp (compare Location.getElapsedRealTimeNanos() with SystemClock.elapsedRealTimeNanos()) then register a listener if the fix is too old.