0

I am using Fedor's example from What is the simplest and most robust way to get the user's current location on Android? in my application. Everything works, but I need the app to show the GPS location if it is available while all the providers are enabled. It will show GPS when just the standalone GPS services are enabled on the device, but as soon as the other location services are turned on, it shows the network location and not the GPS. I need the app to show GPS location if it is available. Even after removing the statement that tells it use the most current one, it still shows network location if it is available. This is my first experience with location services on Android, so any help is greatly appreciated.

 import java.util.Timer;
 import java.util.TimerTask;
 import android.content.Context;
 import android.location.Criteria;
 import android.location.Location;
 import android.location.LocationListener;
 import android.location.LocationManager;
 import android.os.Bundle;

public class MyLocation {
Timer timer1;
LocationManager lm;
LocationResult locationResult;
boolean gps_enabled=false;
boolean network_enabled=false;

public boolean getLocation(Context context, LocationResult result)
{
    //I use LocationResult callback class to pass location value from MyLocation to user code.
    locationResult=result;
    if(lm==null)
        lm = (LocationManager) context.getSystemService(Context.LOCATION_SERVICE);

    //exceptions will be thrown if provider is not permitted.
    try{gps_enabled=lm.isProviderEnabled(LocationManager.GPS_PROVIDER);}catch(Exception ex){}
    try{network_enabled=lm.isProviderEnabled(LocationManager.NETWORK_PROVIDER);}catch(Exception ex){}

    //don't start listeners if no provider is enabled
    if(!gps_enabled && !network_enabled)
        return false;

    if(gps_enabled)
        lm.requestLocationUpdates(LocationManager.GPS_PROVIDER, 0, 0, locationListenerGps);
    if(network_enabled)
        lm.requestLocationUpdates(LocationManager.NETWORK_PROVIDER, 0, 0, locationListenerNetwork);
    timer1=new Timer();
    timer1.schedule(new GetLastLocation(), 20000);
    return true;
}

LocationListener locationListenerGps = new LocationListener() {
    public void onLocationChanged(Location location) {
        timer1.cancel();
        locationResult.gotLocation(location);
        lm.removeUpdates(this);
        lm.removeUpdates(locationListenerNetwork);
    }
    public void onProviderDisabled(String provider) {}
    public void onProviderEnabled(String provider) {}
    public void onStatusChanged(String provider, int status, Bundle extras) {}
};

LocationListener locationListenerNetwork = new LocationListener() {
    public void onLocationChanged(Location location) {
        timer1.cancel();
        locationResult.gotLocation(location);
        lm.removeUpdates(this);
        lm.removeUpdates(locationListenerGps);
    }
    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);
        lm.removeUpdates(locationListenerNetwork);

        Criteria criteria = new Criteria();
        criteria.setAccuracy(Criteria.ACCURACY_FINE);
        criteria.setAltitudeRequired(false);
        criteria.setBearingRequired(false);
        criteria.setCostAllowed(false);
        criteria.setPowerRequirement(Criteria.POWER_HIGH);
        String provider = lm.getBestProvider(criteria, true);

        Location net_loc = null, gps_loc = null;
        if (gps_enabled)
            gps_loc = lm.getLastKnownLocation(provider);
        if (network_enabled)
            net_loc = lm.getLastKnownLocation(provider);

        // if there are both values use GPS
        if (gps_loc != null && net_loc != null) {

            locationResult.gotLocation(gps_loc);

            return;
        }

        if (gps_loc != null) {
            locationResult.gotLocation(gps_loc);
            return;
        }
        if (net_loc != null) {
            locationResult.gotLocation(net_loc);
            return;
        }
        locationResult.gotLocation(null);
    }
}

public static abstract class LocationResult {
    public abstract void gotLocation(Location location);
}
Community
  • 1
  • 1
Jasonwilliams10
  • 292
  • 1
  • 4
  • 17

1 Answers1

0

Using the single criteria criteria.setAccuracy(Criteria.ACCURACY_FINE); works for me selecting network/gps correctly. For all others, I use the default. That may be your issue. You can always call getProviders and select between network and gps yourself.

From the code you posted, it is not clear how you know the difference between the network and gps locations. Are you logging the provider you get back from getBestProvider? Note the following code does not do what you think it is doing --

if (gps_enabled)
        gps_loc = lm.getLastKnownLocation(provider);
if (network_enabled)
        net_loc = lm.getLastKnownLocation(provider);

gps_loc and net_loc will always be the same when both gps_enabled and network_enabled are true, because "provider" is going to be the same (the 'best' one returned by getBestProvider).

I also notice you are extending the TimerTask. In the class you turn off your location updates. You should only need to poll with your task or have periodic updates through a LocationListener. The latter is the preferred method, but either way you should not need to do both.

I recommend looking at Making Your App Location Aware. There is even a section on using both network and gps and selecting the one with best accuracy.

iagreen
  • 31,470
  • 8
  • 76
  • 90
  • I edited my original post to show the entire code I am using for getting the location if it will help. I was afraid that the code I posted was not doing what I thought it was. I was wondering about the timer as well. I have noticed that it works fine on ICS, but when it is installed on a Jelly Bean device, it is causing the app to force close. – Jasonwilliams10 Dec 16 '12 at 21:24