FusedLocationProviderApi doesn't work without network location provider: use SettingsApi for checking and setting up user's configuration
TL;DR
- FusedLocationProviderApi sometimes doesn't work even when your user believes GPS is on
- You can use SettingsApi to check user's configuration and help them setting up necessary location preference
Google introduced FusedLocationProviderApi to Google Play Service library in Google I/O 2013. It provides a battery-efficient, better location service by utilizing both GPS-based location and network-based location.
However, I noticed FusedLocationProviderApi doesn't give any location when user's setting is like below:
Why? Because user just allowing location access to app, but he/she doesn't allow location access to Google (!)
It seems in old age, Android has separate preference titled Google app location settings. However, we no longer have it in my Android L. What I see is a three-level settings: "High accuracy", "Battery saving" and "Device only". And to my surprise, user need to allow location access from Google app if he/she choose "High accuracy" or "Battery saving" mode.
Confusing? Here is a good news - Google recently introduced SettingsApi to check if user satisfy this complex requirement and if not, you can show a dialog to let user recover from the invalid status without leaving app. Some first-party app, like Google map also uses the same dialog.
You can check following code to check user's location setting:
PendingResult<> result = LocationServices.SettingsApi.checkLocationSettings(
mGoogleApiClient,
new LocationSettingsRequest.Builder().addLocationRequest(createLocationRequest()).build());
result.setResultCallback(new ResultCallback<LocationSettingsResult>() {
@Override
public void onResult(LocationSettingsResult locationSettingsResult) {
final Status status = locationSettingsResult.getStatus();
switch (status.getStatusCode()) {
case LocationSettingsStatusCodes.SUCCESS:
// Location is available
break;
case LocationSettingsStatusCodes.RESOLUTION_REQUIRED:
// Location is not available, but we can ask permission from users
break;
case LocationSettingsStatusCodes.SETTINGS_CHANGE_UNAVAILABLE:
// Location is not available, and we cannot recover from the situation
break;
}}});
}
If we reach LocationSettingsStatusCodes.RESOLUTION_REQUIRED, user's setting is not sufficient for LocationRequest. You can use
status.startResolutionForResult(this /* activity */, REQUEST_LOCATION_SET);
to show a dialog to ask user to turn on GPS or Wifi location provider and listen whether user accept it or not at Activity#onResult
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
if (requestCode == REQUEST_LOCATION_SET) {
switch (resultCode) {
case Activity.RESULT_OK:
// TODO
break;
case Activity.RESULT_CANCELED:
// TODO
break;
}
}
}