[android] Show "turn on Google's location service" dialog

In very rare case Google Location Provider asks user to enable
Wi-Fi for "for a better (?surveillance) experience":

1. Airplane is OFF;
2. Wi-Fi is OFF;
3. GPS is OFF;

Before this patch the app just downgraded to use the system location
provider, which waited until HW GPS is found.

With this patch the app dispalys "For a better experience, turn on
device location, which uses Google's location settings". Pressing
"Yes" just enables Wi-Fi without any other changes in the system.
There are no other practical outcomes to users other than reminding
about disabled Wi-Fi.

Signed-off-by: Roman Tsisyk <roman@tsisyk.com>
This commit is contained in:
Roman Tsisyk 2022-10-05 11:32:34 +03:00 committed by Alexander Borsuk
parent 5f4e2a5017
commit e2f1646fcd
3 changed files with 64 additions and 1 deletions

View file

@ -7,6 +7,8 @@ import android.os.Looper;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import com.google.android.gms.common.api.ApiException;
import com.google.android.gms.common.api.ResolvableApiException;
import com.google.android.gms.location.FusedLocationProviderClient;
import com.google.android.gms.location.LocationAvailability;
import com.google.android.gms.location.LocationCallback;
@ -14,6 +16,7 @@ import com.google.android.gms.location.LocationRequest;
import com.google.android.gms.location.LocationResult;
import com.google.android.gms.location.LocationServices;
import com.google.android.gms.location.LocationSettingsRequest;
import com.google.android.gms.location.LocationSettingsStatusCodes;
import com.google.android.gms.location.SettingsClient;
import com.mapswithme.util.log.Logger;
@ -87,6 +90,25 @@ class GoogleFusedLocationProvider extends BaseLocationProvider
Logger.d(TAG, "Service is available");
mFusedLocationClient.requestLocationUpdates(locationRequest, mCallback, Looper.myLooper());
}).addOnFailureListener(e -> {
try
{
int statusCode = ((ApiException) e).getStatusCode();
if (statusCode == LocationSettingsStatusCodes.RESOLUTION_REQUIRED)
{
// Location settings are not satisfied, but this can
// be fixed by showing the user a dialog
Logger.w(TAG, "Resolution is required");
ResolvableApiException resolvable = (ResolvableApiException) e;
mListener.onLocationResolutionRequired(resolvable.getResolution());
return;
}
}
catch (ClassCastException ex)
{
// Ignore, should be an impossible error.
// https://developers.google.com/android/reference/com/google/android/gms/location/SettingsClient
Logger.e(TAG, "An error that should be impossible: " + ex);
}
Logger.e(TAG, "Service is not available: " + e);
mListener.onLocationDisabled();
});

View file

@ -14,6 +14,8 @@ abstract class BaseLocationProvider
@UiThread
void onLocationChanged(@NonNull Location location);
@UiThread
void onLocationResolutionRequired(@Nullable PendingIntent pendingIntent);
@UiThread
void onLocationDisabled();
}

View file

@ -3,14 +3,18 @@ package com.mapswithme.maps.location;
import static android.Manifest.permission.ACCESS_COARSE_LOCATION;
import static android.Manifest.permission.ACCESS_FINE_LOCATION;
import android.app.Activity;
import android.app.Dialog;
import android.app.PendingIntent;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.IntentSender;
import android.location.Location;
import android.location.LocationManager;
import androidx.activity.result.ActivityResultLauncher;
import androidx.activity.result.IntentSenderRequest;
import androidx.activity.result.contract.ActivityResultContracts;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
@ -85,7 +89,9 @@ public enum LocationHelper implements Initializable<Context>, AppBackgroundTrack
@Nullable
private Dialog mLocationErrorDialog;
@Nullable
ActivityResultLauncher<String[]> mPermissionRequest;
private ActivityResultLauncher<String[]> mPermissionRequest;
@Nullable
private ActivityResultLauncher<IntentSenderRequest> mResolutionRequest;
@SuppressWarnings("FieldCanBeLocal")
private final LocationState.ModeChangeListener mMyPositionModeListener =
@ -307,6 +313,22 @@ public enum LocationHelper implements Initializable<Context>, AppBackgroundTrack
notifyLocationUpdated();
}
@Override
@UiThread
public void onLocationResolutionRequired(@Nullable PendingIntent pendingIntent)
{
Logger.d(TAG, "");
if (mResolutionRequest == null) {
onLocationDisabled();
return;
}
IntentSenderRequest intentSenderRequest = new IntentSenderRequest.Builder(pendingIntent.getIntentSender())
.build();
mResolutionRequest.launch(intentSenderRequest);
}
@Override
@UiThread
public void onLocationDisabled()
@ -576,6 +598,9 @@ public enum LocationHelper implements Initializable<Context>, AppBackgroundTrack
mPermissionRequest = mUiCallback.requireActivity()
.registerForActivityResult(new ActivityResultContracts.RequestMultiplePermissions(),
result -> onRequestPermissionsResult());
mResolutionRequest = mUiCallback.requireActivity()
.registerForActivityResult(new ActivityResultContracts.StartIntentSenderForResult(),
result -> onLocationResolutionResult(result.getResultCode()));
if (!Config.isScreenSleepEnabled()) {
Utils.keepScreenOn(true, mUiCallback.requireActivity().getWindow());
@ -614,6 +639,8 @@ public enum LocationHelper implements Initializable<Context>, AppBackgroundTrack
Utils.keepScreenOn(false, mUiCallback.requireActivity().getWindow());
mPermissionRequest.unregister();
mPermissionRequest = null;
mResolutionRequest.unregister();
mResolutionRequest = null;
mUiCallback = null;
}
@ -650,6 +677,18 @@ public enum LocationHelper implements Initializable<Context>, AppBackgroundTrack
restart();
}
@UiThread
private void onLocationResolutionResult(int resultCode)
{
if (resultCode != Activity.RESULT_OK)
{
onLocationDisabled();
return;
}
restart();
}
@UiThread
public boolean isInFirstRun()
{