Android Gps Incorrect Location Data on Query

Android GPS incorrect location data on query

From what is specified[difference of 4-5 blocks], you may be obtaining the location from networkProvider only.

With this gpsTracker code mentioned in the question,

there are a few modifications required, instead of using the code as it is:

1.
There are 2 if loops which verify the source of location is enabled or not and No 'else':

 if (isNetworkEnabled) {
locationManager.requestLocationUpdates(
LocationManager.NETWORK_PROVIDER,
MIN_TIME_BW_UPDATES,
MIN_DISTANCE_CHANGE_FOR_UPDATES, this);
Log.d("Network", "Network");
if (locationManager != null) {
location = locationManager
.getLastKnownLocation(LocationManager.NETWORK_PROVIDER);
if (location != null) {
latitude = location.getLatitude();
longitude = location.getLongitude();
}
}
}
// if GPS Enabled get lat/long using GPS Services
if (isGPSEnabled) {
if (location == null) {
locationManager.requestLocationUpdates(
LocationManager.GPS_PROVIDER,
MIN_TIME_BW_UPDATES,
MIN_DISTANCE_CHANGE_FOR_UPDATES, this);
Log.d("GPS Enabled", "GPS Enabled");
if (locationManager != null) {
location = locationManager
.getLastKnownLocation(LocationManager.GPS_PROVIDER);
if (location != null) {
latitude = location.getLatitude();
longitude = location.getLongitude();
}
}
}
}

This means the application is going to do twice the work when you can obtain the location from both sources. Further, the source of location obtained always remains ambiguous.

This is good when you just need approximate location which should not be null majorly.

If you want to use only this class to obtain location, try structuring the if-else according to requirement and ensuring that its not going to repeat if the location is obtained.

Eg. if GPS is on a higher preference, applies in your case, shift that if above and put the network condition with an else like:

if (isGPSEnabled) {
if (location == null) {
locationManager.requestLocationUpdates(
LocationManager.GPS_PROVIDER,
MIN_TIME_BW_UPDATES,
MIN_DISTANCE_CHANGE_FOR_UPDATES, this);
Log.d("GPS Enabled", "GPS Enabled");
if (locationManager != null) {
location = locationManager
.getLastKnownLocation(LocationManager.GPS_PROVIDER);
if (location != null) {
latitude = location.getLatitude();
longitude = location.getLongitude();
}
}
}
} else if (isNetworkEnabled) {
locationManager.requestLocationUpdates(
LocationManager.NETWORK_PROVIDER,
MIN_TIME_BW_UPDATES,
MIN_DISTANCE_CHANGE_FOR_UPDATES, this);
Log.d("Network", "Network");
if (locationManager != null) {
location = locationManager
.getLastKnownLocation(LocationManager.NETWORK_PROVIDER);
if (location != null) {
latitude = location.getLatitude();
longitude = location.getLongitude();
}
}
}

For your requirement, i suggest removing the network provider part and obtaining the location only from GPS, esp if line of sight is not a problem.

When your code was working fine, it must be fetching the location from GPS and setting it in the object. But because of the two "if" and no "else", you'l never know whether location obtained is from Network or GPS - you can check location.getProvider() inside the condition of canGetLocation()

2.
Also, you can log the message or prompt some action for one particular source...like:

In this part:

 if (!isGPSEnabled && !isNetworkEnabled) {
// no network provider is enabled
}

just separate it into two different if(s) and code accordingly. As of now, nothing happens here so you wouldn't know if both are disabled unless you check it externally.

Suggestion: Try the LocationClient which uses GooglePlayServices for Retrieving Current Location . I have found it more reliable and useful. Check this Fused Location Provider example, setting LocationRequest object according to your requirement is the key.

Another update: just came across: useful ques on stack overflow - Good way of getting the users location


Update for anybody looking up this question/answer
Regarding the suggestion of LocationClient;

LocationClient is no longer found under com.google.android.gms.location, refer:

Android play services 6.5: LocationClient is missing

Variation in GPS data being at same location

After working on many methods I programmed it with bearing.

I am getting speed based on last 5 locations. I added Logic to check bearing for each location with next location and if all bearing have larger difference, I assumed locations are being received from random directions and so the device is not actually moving.

And it worked great for me :)

LocationManager is sending Last location all time

you are using network location which doesn't provide the correct location rather than using network location you should use the GPS location for current and accurate location.

getLastKnowLocation() method doesn't provide the correct , current location for this you can refer this link.

rather than using network location use GPS location and you can find the good example of GPS location from the given link.

http://www.androidhive.info/2012/07/android-gps-location-manager-tutorial/

Latitude and longitude not retrieved

I assume you are calling doInBackground() method in onCreate() method of your activity So if GPS is not enabled then your application is redirected to GPS settings screen.

So when you come back from GPS settings screen after enabling it your Activity resume so it will not call doInBackground() again that's why you don't get any result.

Simplest solution is to define onResume() method for your Activity and call doInBackground() in onResume() rather than onCreate() so when your Activity resume so it will call doInBackground() again you get updated result.

You should update your Whether Activity like this:

public class Weather extends AppCompatActivity{

@Override
protected void onCreate(Bundle savedInstanceState){
super.onCreate(savedInstanceState);
setContentView(R.layout.meteo_nuovo);

Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar_layout);
setSupportActionBar(toolbar);

toolbar.setPadding(0, getStatusBarHeight(), 0, 0);

assert getSupportActionBar() != null;

this.getSupportActionBar().setDisplayHomeAsUpEnabled(true);
this.getSupportActionBar().setDisplayShowTitleEnabled(false);

if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) {
getWindow().getDecorView().setSystemUiVisibility(
View.SYSTEM_UI_FLAG_LAYOUT_STABLE
| View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN);
}
}

@Override
public void onResume(){
super.onResume();
new WeatherApi(this).execute(); // the doInBackground method above is from this class

}

public int getStatusBarHeight() {
int result = 0;

if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.KITKAT) {
int resourceId = getResources().getIdentifier("status_bar_height", "dimen", "android");
if (resourceId > 0) {
result = getResources().getDimensionPixelSize(resourceId);
}
}
return result;
}

@Override
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
case android.R.id.home:
finish();
return true;
default:
return super.onOptionsItemSelected(item);
}
}
}

I hope it helps you.

how can i get continuous updates of current location in android

You are causing it to stop listening after the first location.

public void onLocationChanged(Location location) 
{
if (location != null)
{
// This needs to stop getting the location data and save the battery power.
locManager.removeUpdates(this); <-- REMOVE THIS LINE

inaccurate altitude readings from gps

" it shows good altitude during rest of the walk/ride?"

I doubt that altitude is good on the rest of your ride.

altitude via GPS is known to be not very usefull. The error is about twice that of horicontal (lat,lon) error. Thats the reason why professional navigation devices additionally use a barometer sensor instead of GPS altitude alone.

The reason why it gets better, is that the averaging algorithm had more time to average the errors out. On my ios devcie and i my app, the altitude jumps so much that it shows some hundreds meters ascending / descending even when I am moving level at a lake.

But you always can check the value of vertical accuracy. Use the altitude only when it gets below 30m vert. accuracy.

Application getting wrong location until open inbuilt Google Map application

So Waze and we used FusedLocation in past and faced a lot of problems.
The API is broken. There are some devices that not perf it properly. Activity recognition that fused a lot relay not working and recognize staff properly.
We end, to switching back to location manager API.

Here the snippet:

Init location manager and start to request the updates on different thread.
I personally register separate listeners for each provider

if (mLocationManager == null) {
LOGGER.info("Location track,start called first time. Creating Location Manager");
mLocationManager = (LocationManager) mContextWeakReference.get()
.getSystemService(Context.LOCATION_SERVICE);

mLocationHandlerThread
= new HandlerThread("LocationThread", Thread.NORM_PRIORITY);
mLocationHandlerThread.start();
// Now get the Looper from the HandlerThread
// NOTE: This call will block until the HandlerThread gets control and initializes its Looper
Looper looper = mLocationHandlerThread.getLooper();
Location networkLastKnownLocation = null;
Location gpsLastKnownLocation = null;
mGpsLocationListener = new GpsLocationListener();
mNetworkLocationListener = new NetworkLocationListener();

// Register the listener with the Location Manager to receive location updates
if (mLocationManager.getAllProviders().contains(LocationManager.GPS_PROVIDER)) {
mLocationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER,
LOCATION_REQUEST_INTERVAL_MILLIS, SMALLEST_DISPLACEMENT_METERS,
mGpsLocationListener,
looper);

gpsLastKnownLocation = mLocationManager
.getLastKnownLocation(LocationManager.GPS_PROVIDER);
} else {
setGpsProviderAvailable(false);
}
if (mLocationManager.getAllProviders().contains(LocationManager.NETWORK_PROVIDER)) {
networkLastKnownLocation = mLocationManager
.getLastKnownLocation(LocationManager.NETWORK_PROVIDER);
mLocationManager.requestLocationUpdates(LocationManager.NETWORK_PROVIDER,
LOCATION_REQUEST_INTERVAL_MILLIS, SMALLEST_DISPLACEMENT_METERS,
mNetworkLocationListener,
looper);
}

setLastKnownLocationDifferentProviders(gpsLastKnownLocation,
networkLastKnownLocation);

}

And the listeners are:

public class GpsLocationListener implements LocationListener {

@Override
public void onLocationChanged(Location location) {
LOGGER.info("Location track ,onLocationChanged location={}", location);
switch (location.getProvider()) {
case LocationManager.GPS_PROVIDER:
if (mLocationManager != null) {
mLocationManager.removeUpdates(mNetworkLocationListener);
}
break;
}
setLastKnownLocation(location);
}

@Override
public void onStatusChanged(String provider, int status, Bundle extras) {
LOGGER.info("onStatusChanged: {}, status: {}", provider, status);
}

@Override
public void onProviderEnabled(String provider) {
LOGGER.info("onProviderEnabled: " + provider);
if (provider.equals(LocationManager.GPS_PROVIDER)) {
setGpsProviderAvailable(true);
}
}

@Override
public void onProviderDisabled(String provider) {
LOGGER.info("onProviderDisabled: " + provider);
if (provider.equals(LocationManager.GPS_PROVIDER)) {
setGpsProviderAvailable(false);
}
}
}

public class NetworkLocationListener implements LocationListener {

@Override
public void onLocationChanged(Location location) {
LOGGER.info("Location track ,onLocationChanged location={}", location);
switch (location.getProvider()) {
case LocationManager.NETWORK_PROVIDER:
setLastKnownLocation(location);
break;
}
}

@Override
public void onStatusChanged(String provider, int status, Bundle extras) {
LOGGER.info("onStatusChanged: {}, status: {}", provider, status);
}

@Override
public void onProviderEnabled(String provider) {
LOGGER.info("onProviderEnabled: " + provider);
if (provider.equals(LocationManager.GPS_PROVIDER)) {
setGpsProviderAvailable(true);
}
}

@Override
public void onProviderDisabled(String provider) {
LOGGER.info("onProviderDisabled: " + provider);
if (provider.equals(LocationManager.GPS_PROVIDER)) {
setGpsProviderAvailable(false);
}
}
}

Don't forgot to unregister and stop all threads :)



Related Topics



Leave a reply



Submit