6

This is weird. I mean, I have strong network, and GPS is turned On, still it asks for Wifi !!

I'm using new Location Api with class FusedLocationProviderClient.

This is how I am checking if Location Settings are enabled or not:

private void checkIfLocationSettingsAreEnabled() {
    LocationRequest locationRequest = new LocationRequest();
    locationRequest.setPriority(LocationRequest.PRIORITY_BALANCED_POWER_ACCURACY);
    locationRequest.setInterval(10000);
    locationRequest.setFastestInterval(5000);

    LocationSettingsRequest.Builder builder = new LocationSettingsRequest.Builder();
    builder.addLocationRequest(locationRequest);
    builder.setAlwaysShow(true);

    SettingsClient client = LocationServices.getSettingsClient(context);
    Task<LocationSettingsResponse> locationSettingsResponseTask = client.checkLocationSettings(builder.build());
    locationSettingsResponseTask.addOnSuccessListener(locationSettingsResponse -> {
        getLastKnownLocation();
    });
    locationSettingsResponseTask.addOnFailureListener(e -> {
        if (e instanceof ResolvableApiException) {
            myLocationListener.onResolutionNeeded(e);
        } else {
            myLocationListener.onLocationFailure(e);
        }
    });
}

With the above code, I am able to get below image:

enter image description here

But then, after clicking OK, again I make call to checkIfSettingsAreEnabled() this shows another popup as below:

enter image description here

I wonder why enabling Wifi is mandatory, even if I am on desert safari, where there is no Wifi to connect to !!

Is there any way to Skip this Wifi option, and work as normal as Google Maps does ?

In fact, Google Maps uses priority PRIORITY_HIGH_ACCURACY and still once, the first settings dialog has been shown, it doesn't ask second time to turn on Wifi.

Chintan Soni
  • 24,761
  • 25
  • 106
  • 174

3 Answers3

2

FusedLocationProvider uses a combo of GPS and WIFI to get your location. Especially when asking for balanced mode, it needs both or won't work (GPS takes power, so it won't rely just on it for balanced). Try max accuracy, its less likely to use it then. Or just use the GPS provider if you actually want GPS.

sharp
  • 1,191
  • 14
  • 39
Gabe Sechan
  • 90,003
  • 9
  • 87
  • 127
0

PRIORITY_BALANCED_POWER_ACCURACY

This priority will go with coarse level accuracy which fetch location only from wi-fi , cellular network or bluetooth and NOT from GPS.

and if device don't have SIM it needs to have wi-fi to get location or it will not call onLocationChanged till won't get location.

Sanket Kachhela
  • 10,861
  • 8
  • 50
  • 75
0

With the below solution, I am able to skip this Wifi Settings Dialog. This is not a perfect solution, but just a workaround till I find perfect solution.

Problem was, even after clicking "Ok" on Settings Dialog, it returned result as Activity.RESULT_CANCELLED. Reason was, Wifi was still turned off. So, as a quick fix, made a check in result Activity.RESULT_CANCELLED, that if I could get Location by checking LocationSettingStates.

You can use my MyLocationUtils.java and Base classes LocationActivity.java or LocationFragment.java. Happy Coding..!!

for getting location

MyLocationUtils.java:

public class MyLocationUtils {

    public static final int REQUEST_CODE_LOCATION_SETTINGS = 123;

    private static final int INTERVAL_IN_MS = 10000;
    private static final int FASTEST_INTERVAL_IN_MS = 5000;
    private static final int MAX_WAIT_TIME_IN_MS = 5000;
    private static final int NUMBER_OF_UPDATES = 1;

    private final MyLocationListener myLocationListener;
    private final Context context;
    private FusedLocationProviderClient mFusedLocationProviderClient;
    private LocationCallback mLocationCallback = new LocationCallback() {
        @Override
        public void onLocationResult(LocationResult locationResult) {
            super.onLocationResult(locationResult);

            Location location = null;
            if (locationResult.getLocations().size() > 0) {
                location = locationResult.getLocations().get(0);
            }

            myLocationListener.onLocationSuccess(location);

            stopContinuousLocation();
        }
    };

    public MyLocationUtils(Context context, MyLocationListener myLocationListener) {
        this.context = context;
        this.myLocationListener = myLocationListener;

        initializeFusedLocationProviderClient();
    }

    private boolean checkIfRequiredLocationSettingsAreEnabled(Context context) {
        LocationManager locationManager = (LocationManager) context.getSystemService(Context.LOCATION_SERVICE);
        return locationManager.isProviderEnabled(LocationManager.GPS_PROVIDER) || locationManager.isProviderEnabled(LocationManager.NETWORK_PROVIDER);
    }

    private void initializeFusedLocationProviderClient() {
        mFusedLocationProviderClient = LocationServices.getFusedLocationProviderClient(context);
    }

    public void stopContinuousLocation() {
        mFusedLocationProviderClient.removeLocationUpdates(mLocationCallback);
    }

    public void getLocation() {
        checkIfLocationSettingsAreEnabled();
    }

    private void checkIfLocationSettingsAreEnabled() {
        if (checkIfRequiredLocationSettingsAreEnabled(context)) {
            getLastKnownLocation();
        } else {
            LocationSettingsRequest.Builder builder = new LocationSettingsRequest.Builder();
            builder.addLocationRequest(getLocationRequest());
            builder.setAlwaysShow(true);

            SettingsClient client = LocationServices.getSettingsClient(context);
            Task<LocationSettingsResponse> locationSettingsResponseTask = client.checkLocationSettings(builder.build());
            locationSettingsResponseTask.addOnSuccessListener(locationSettingsResponse -> {
                // All location settings are satisfied. The client can initialize
                // location requests here.
                // ...
                getLastKnownLocation();
            });
            locationSettingsResponseTask.addOnFailureListener(e -> {
                if (e instanceof ResolvableApiException) {
                    myLocationListener.onResolutionNeeded(e);
                } else {
                    myLocationListener.onLocationFailure(e);
                }
            });
        }
    }

    @SuppressLint("MissingPermission")
    private void getLastKnownLocation() {
        Task<Location> locationTask = mFusedLocationProviderClient.getLastLocation();
        locationTask.addOnSuccessListener(location -> {
            // Got last known location. In some rare situations this can be null.
            if (location != null) {
                myLocationListener.onLocationSuccess(location);
            } else {
                startContinuousLocation();
            }
        });
        locationTask.addOnFailureListener(myLocationListener::onLocationFailure);
    }

    @SuppressLint("MissingPermission")
    private void startContinuousLocation() {
        mFusedLocationProviderClient.requestLocationUpdates(getLocationRequest(), mLocationCallback, Looper.getMainLooper())
                .addOnFailureListener(myLocationListener::onLocationFailure);
    }

    private LocationRequest getLocationRequest() {
        LocationRequest locationRequest = new LocationRequest();
        locationRequest.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY);
        locationRequest.setInterval(INTERVAL_IN_MS);
        locationRequest.setFastestInterval(FASTEST_INTERVAL_IN_MS);
        locationRequest.setNumUpdates(NUMBER_OF_UPDATES);
        locationRequest.setMaxWaitTime(MAX_WAIT_TIME_IN_MS);
        return locationRequest;
    }

    public void resolveLocationSettings(FragmentActivity fragmentActivity, Exception exception) {
        ResolvableApiException resolvable = (ResolvableApiException) exception;
        try {
            resolvable.startResolutionForResult(fragmentActivity, MyLocationUtils.REQUEST_CODE_LOCATION_SETTINGS);
        } catch (IntentSender.SendIntentException e1) {
            e1.printStackTrace();
        }
    }

    public interface MyLocationListener {

        void onLocationSuccess(Location location);

        void onResolutionNeeded(Exception exception);

        void onLocationFailure(Exception exception);
    }
}

BaseLocationActivity.java:

public abstract class LocationActivity extends AppCompatActivity {

    private MyLocationUtils myLocationUtils;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        myLocationUtils = new MyLocationUtils(this, new MyLocationUtils.MyLocationListener() {
            @Override
            public void onLocationSuccess(Location location) {
                if (shouldBeAllowedToProceed())
                    LocationActivity.this.onLocationSuccess(location);
            }

            @Override
            public void onResolutionNeeded(Exception exception) {
                exception.printStackTrace();
                if (shouldBeAllowedToProceed())
                    LocationActivity.this.onResolutionNeeded(exception);
            }

            @Override
            public void onLocationFailure(Exception exception) {
                exception.printStackTrace();
                if (shouldBeAllowedToProceed())
                    LocationActivity.this.onLocationFailure(exception);
            }
        });
    }

    protected void getLocation() {
        myLocationUtils.getLocation();
    }

    protected void resolveLocationSettings(Exception exception) {
        myLocationUtils.resolveLocationSettings(this, exception);
    }

    @Override
    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
        if (requestCode == MyLocationUtils.REQUEST_CODE_LOCATION_SETTINGS) {
            final LocationSettingsStates locationSettingsStates = LocationSettingsStates.fromIntent(data);
            switch (resultCode) {
                case Activity.RESULT_OK:
                    onResolveLocationSettingOk();
                    break;
                case Activity.RESULT_CANCELED:
                    // The user was asked to change settings, but chose not to, 
                    // or on Android Oreo 8.1 Wifi Settings were not satisfied inspite of clicking OK, that results on Activity.RESULT_CANCELED
                    onResolveLocationSettingCancelled(locationSettingsStates);
                    break;
                default:
                    break;
            }
        }
    }

    protected abstract void onResolveLocationSettingOk();

    protected void onResolveLocationSettingCancelled(LocationSettingsStates locationSettingsStates) {
        if (locationSettingsStates.isLocationPresent() && locationSettingsStates.isLocationUsable()) {
            onResolveLocationSettingOk();
        }
    }

    private boolean shouldBeAllowedToProceed() {
        return getLifecycle().getCurrentState().isAtLeast(Lifecycle.State.RESUMED);
    }

    public abstract void onLocationSuccess(Location location);

    public abstract void onResolutionNeeded(Exception exception);

    public abstract void onLocationFailure(Exception exception);

    @Override
    public void onDestroy() {
        super.onDestroy();
        myLocationUtils.stopContinuousLocation();
    }
}

LocationFragment.java:

public abstract class LocationFragment extends Fragment {

    private MyLocationUtils myLocationUtils;

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        myLocationUtils = new MyLocationUtils(context, new MyLocationUtils.MyLocationListener() {
            @Override
            public void onLocationSuccess(Location location) {
                if (shouldBeAllowedToProceed())
                    LocationFragment.this.onLocationSuccess(location);
            }

            @Override
            public void onResolutionNeeded(Exception exception) {
                exception.printStackTrace();
                if (shouldBeAllowedToProceed())
                    LocationFragment.this.onResolutionNeeded(exception);
            }

            @Override
            public void onLocationFailure(Exception exception) {
                exception.printStackTrace();
                if (shouldBeAllowedToProceed())
                    LocationFragment.this.onLocationFailure(exception);
            }
        });
    }

    protected void resolveLocationSettings(FragmentActivity appCompatActivity, Exception exception) {
        myLocationUtils.resolveLocationSettings(appCompatActivity, exception);
    }

    @Override
    public void onActivityResult(int requestCode, int resultCode, Intent data) {
        if (requestCode == MyLocationUtils.REQUEST_CODE_LOCATION_SETTINGS) {
            final LocationSettingsStates locationSettingsStates = LocationSettingsStates.fromIntent(data);
            switch (resultCode) {
                case Activity.RESULT_OK:
                    onResolveLocationSettingOk();
                    break;
                case Activity.RESULT_CANCELED:
                    // The user was asked to change settings, but chose not to
                    onResolveLocationSettingCancelled(locationSettingsStates);
                    break;
                default:
                    break;
            }
        }
    }

    protected abstract void onResolveLocationSettingOk();

    protected void onResolveLocationSettingCancelled(LocationSettingsStates locationSettingsStates) {
        if (locationSettingsStates.isLocationPresent() && locationSettingsStates.isLocationUsable()) {
            onResolveLocationSettingOk();
        }
    }

    public void getLocation() {
        myLocationUtils.getLocation();
    }

    private boolean shouldBeAllowedToProceed() {
        return getLifecycle().getCurrentState().isAtLeast(Lifecycle.State.RESUMED);
    }

    public abstract void onLocationSuccess(Location location);

    public abstract void onResolutionNeeded(Exception exception);

    public abstract void onLocationFailure(Exception exception);

    @Override
    public void onDestroy() {
        super.onDestroy();
        myLocationUtils.stopContinuousLocation();
    }
}
Chintan Soni
  • 24,761
  • 25
  • 106
  • 174