So I have the following code:
LocationManager locationManager = (LocationManager) this.getSystemService(Context.LOCATION_SERVICE);
LocationListener locationListener = new LocationListener() {
public void onLocationChanged(Location location) {
makeUseOfNewLocation(location);
}
public void onStatusChanged(String provider, int status, Bundle extras) {}
public void onProviderEnabled(String provider) {}
public void onProviderDisabled(String provider) {}
};
locationManager.requestLocationUpdates(LocationManager.NETWORK_PROVIDER, Integer.MAX_VALUE, 1 locationListener);
From http://developer.android.com/guide/topics/location/strategies.html
But the thing is I want to call makeUseOfNewLocation(location); every 1 meter, I walked through my house(with my internet from the provider ON) and still did not manage to get in makeUseOfNewLocation(Location location).
I am using Integer.MAX_VALUE because the time for request does not matter.
How can I fix the problem? Can you help me?
The second parameter where you have Integer.MAX_VALUE is where you put in the distance.
See the documentation for LocationManager at http://developer.android.com/reference/android/location/LocationManager.html#requestLocationUpdates(long, float, android.location.Criteria, android.app.PendingIntent)
1f instead of Integer.MAX_VALUE should do it, provided everything else is OK.
Edit Actually, check the documentation. Looks like your call there is more than a bit inaccurate (for what you are trying to do -- looks like wrong version of the function).
Edit #2 Based on your reply, you have set infinity as the minimum time between updates. Try 0f. Also, for the minDistance, try 1f instead of 1 to ensure it is a float.
Related
My app uses google map to show user's location in real time. Therefore I would like it to be updated with every data change on my Parse server.
I've looked all over the net and as I see it I have 3 options:
using syncAdapter - the problem is that everywhere it is written that it does not meant for real time data transfer (I don't really understand why), on other hand it must be more efficient than updating every 5 sec.
using asyncTask - the problem is that it probably consumes a lot of battery and data usage to run it every 5 sec.
using service - same problem as asyncTask.
As i'm very confused, please help me understand what is the appropriate way to implement my real time map.
Thank's all
The best way i know is to use LocationListener to update the location only if it has been changed. You can use the onLocationChanged() method to update the location.
public class LocationHelper {
private LocationManager locationManager;
private Location currentLocation;
public LocationHelper(Context context) {
locationManager = (LocationManager) context.getSystemService(Context.LOCATION_SERVICE);
locationManager.removeUpdates(locationListener);
locationManager.requestLocationUpdates(LocationManager.NETWORK_PROVIDER, 0, 0, locationListener);
}
public void setLocation(Location location) {
currentLocation = location;
}
private final LocationListener locationListener = new LocationListener() {
#Override
public void onLocationChanged(Location location) {
setLocation(location);//Only update location if it has changed.
}
#Override
public void onStatusChanged(String provider, int status, Bundle extras) {}
#Override
public void onProviderEnabled(String provider) {}
#Override
public void onProviderDisabled(String provider) {}
};
}
If the location hasn't been changed, you can just remember the last known location.
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 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!
It seems for me it is getting called the first time the activity starts, just after onCreate, it then seems to be called at random intervals, whether I move or not???
Regardless of that is it simply called automatically if I have code like this in the onCreate method?
locationManager = (LocationManager) getSystemService(LOCATION_SERVICE);
Criteria criteria = new Criteria();
Is that right???
Cheers,
Mike.
Your question is not clear initially.Your code and title are not matching. I am giving answer for your title only.
You have to register Location Listener for your Location Manager, then only onLocationChanged() will be called according the settings you supplied while registering location listener.
See below code how to do that. I used GPS Provider, you can use any provider based on criteria also.
LocationManger lm = (LocationManager)getSystemService(Context.LOCATION_SERVICE);
lm.requestLocationUpdates(LocationManager.GPS_PROVIDER, 1000, 0, new LocationListener() {
#Override
public void onLocationChanged(Location location) {
// TODO Auto-generated method stub
}
#Override
public void onProviderDisabled(String provider) {
// TODO Auto-generated method stub
}
#Override
public void onProviderEnabled(String provider) {
// TODO Auto-generated method stub
}
#Override
public void onStatusChanged(String provider, int status,
Bundle extras) {
// TODO Auto-generated method stub
}
});
Coming to your question, onLocationChanged() will be called if the current location update is not matching with last known location.
The updated location will be changed for every minTime (in my case 1000 milli sec) and also if device moved minDistance (in my case 0 meters) distance.
I hope you will understand this.
if you want to catch new locations, you have to register a LocationListener like this:
LocationManager locationManager = (LocationManager) getSystemService(LOCATION_SERVICE);
LocationListener listener = new LocationListener() {
...
}
locationManager.requestLocationUpdates(GPS_PROVIDER, intervall, distance, listener);
With intervall and distance you can configure:
If intervall is greater than 0, the LocationManager could potentially rest for intervall milliseconds between location updates
If distance is greater than 0, a location will only be broadcasted if the device moves by distance meters.
When the LocationListener is registered, the LocationManager starts to get your geo location and calls the onLocationChanged(). If the distance is very low, it can happen that the method is called very often in a short period of time. According to the intervall, the LocationManager will rest afterwards.
I think, the LocationManager will only start doing it's work, when a LocationListener is registered.
Hope that helps...
Cheers,
Tobi
public void onLocationChanged(Location location)
the above method gets called automatically once your location has been changed..
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.