Iam developing an app that do some field signal strengths calculations every second by using Handler and during the Handler period it records the coordinates and record the results & coordinates. It works fine except when real testing and when I increase the speed of the vehicle the recorded coordinates not every second while some times every 2-3-4 seconds which is not accepted by me.
The Code below:
final LocationManager locationManager = (LocationManager) getSystemService(Context.LOCATION_SERVICE);
locationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, 0, 0, this);
publicvoid method_01(LocationManager locationManager){
final Handler handler = new Handler();
handler.postDelayed(new Runnable() {
#Override
public void run() {
Location locationDataRate = locationManager.getLastKnownLocation(LocationManager.GPS_PROVIDER);
double latitude = locationDataRate.getLatitude();
double longitude = locationDataRate.getLongitude();
x=y+1;
Save to file (latitude,longitude,x);
handler.postDelayed(this, 1000);
}
}, 1000);
}
I have tried also to change the time and min. distance to (1000,0)
First of all, if you want to receive an update every 1 second, you should not request more frequent updates. Therefore:
locationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, 1000, 0, this);
Anyway, the best practice for handling location updates is not persistently looping getLastKnownLocation but implementing the callback of location updates. There is a bundle of examples here.
To your question, in the doc they state that interval between updates in never guaranteed:
The location update interval can be controlled using the minTime
parameter. The elapsed time between location updates will never be
less than minTime, although it can be more depending on the Location
Provider implementation and the update interval requested by other
applications.
Related
I have written this function for requesting location updates:
private void RequestLocations() {
locationListener = new LocationUpdater();
lm = (LocationManager) getSystemService(Context.LOCATION_SERVICE);
if (!lm.isProviderEnabled(LocationManager.GPS_PROVIDER)) {
lm.requestLocationUpdates(LocationManager.NETWORK_PROVIDER,0,
100, locationListener);
} else {
lm.requestLocationUpdates(LocationManager.GPS_PROVIDER, 0, 100,
locationListener);
lm.requestLocationUpdates(LocationManager.NETWORK_PROVIDER,0,
100, locationListener);
}
}
I am calling this function in the onStart() of a service which I have made a foreground service.
In locationUpdater I have implemented locationListener. In on location changed I am toasting lat/lang.
It is working fine if I am at a walking speed.
But while I am driving it is not as accurate and fast as it was with walking speed. Even though it is not toasting any location if I am at a speed of more than 50 KM/h and as soon as I stop it again starts working and toast a new location.
I wanted to make something in which as soon as I move 100 meters away it should toast new location whatever the speed is.
Please guide me and if I am wrong at any place make me correct.
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.
I'm trying to find a way to turn off the GPS immidietly in case a good enough location was found, while still having a time limit to "give up".
I tried to do this with the following strategy:
start checking for locations, as soon as a location that has an accuracy lower than the maximum tolerated, pass it to the next function for processing and stop looking for updates.
Also, to save battery life, if such location could not be found in 30 seconds, stop looking for location updates without passing a value (basically give up, and hope to better luck next time).
To count the 30 seconds, I'm using a handler. But as soon as I write the line locationManager.removeUpdates(locationListener); in the handler, the locationListener in the parenteses in both lines (the one in the handler and the one in the listener) turns red and reports an error: The local variable locationListener may not have been initialized
Here is my code:
private void checkProximity() {
final LocationManager locationManager = (LocationManager) this.getSystemService(Context.LOCATION_SERVICE);
//start tracking location
final LocationListener locationListener = new LocationListener() {
...
#Override
public void onLocationChanged(Location location) {
//if new accuracy is better than the best estimate - update the best estimate
if(location.getAccuracy() < MAXIMUM_TOLERATED_ACCURACY) {
//forward location to scanProximity and end the location search
scanProximity(location);
locationManager.removeUpdates(locationListener); //FIRST LINE (see below)
}
}
};
locationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER,
500, 0, locationListener);
Handler h = new Handler();
int delay = 30 * SECOND;
Runnable removeListener = new Runnable() {
#Override
public void run() {
//if this code is reached - the maximum tolerated accuracy was not met in the period time
//extended to find a location
//TODO stop the location manager and return without forwarding a value
locationManager.removeUpdates(locationListener); //as soon as I write this line, the FIRST LINE and this line turns red.
}
};
h.postDelayed(removeListener, delay);
}
Is there anyway I can do this differently so I won't get an error?
I recommend you use Little Fluffy Location Library to work with GPS locations. Check out the examples codes and see which makes you more easy the solution to your problem , this is a beautiful way.
I am trying the 'LocationUpdates' sample from http://developer.android.com/training/location/receive-location-updates.html . This application gets and prints location notifications.
I am trying to change the interval of the location updates according to my latest location.
So - I had added mLocationRequest.setInterval() into onLocationChanged
The result is very wrong. My application is bombarded with many location updates (few a second!!!!)
My only change to the sample is this:
private int x=0;
#Override
public void onLocationChanged(Location location) {
// Report to the UI that the location was updated
mConnectionStatus.setText(R.string.location_updated);
// In the UI, set the latitude and longitude to the value received
mLatLng.setText(String.valueOf(x++));
mLocationRequest.setInterval(1000); // Change 1
mLocationClient.requestLocationUpdates(mLocationRequest, this); // Change 2
}
How can I change the interval inside onLocationChanged ?
I think that the problem is that requestLocationUpdates resets the last request, and then immediately sends another notification. so a loop is created. (faster than the fastest interval). so I need a reliable way to change the interval of a 'live' LocationRequest
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 anyways mLocationRequest.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.
Try to use :
mLocationRequest.requestLocationUpdates("gps", 1000, 0, this);
However I don't agree to do a requestLocationUpdates in onLocationChanged event; In my opinion should be setted outside onLocationChanged Event...
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.