From e2f1646fcda63ad23ab296295eba17f23c73c69a Mon Sep 17 00:00:00 2001 From: Roman Tsisyk Date: Wed, 5 Oct 2022 11:32:34 +0300 Subject: [PATCH] [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 --- .../location/GoogleFusedLocationProvider.java | 22 ++++++++++ .../maps/location/BaseLocationProvider.java | 2 + .../maps/location/LocationHelper.java | 41 ++++++++++++++++++- 3 files changed, 64 insertions(+), 1 deletion(-) diff --git a/android/flavors/gms-enabled/com/mapswithme/maps/location/GoogleFusedLocationProvider.java b/android/flavors/gms-enabled/com/mapswithme/maps/location/GoogleFusedLocationProvider.java index d75d979bf8..52a2baa7f5 100644 --- a/android/flavors/gms-enabled/com/mapswithme/maps/location/GoogleFusedLocationProvider.java +++ b/android/flavors/gms-enabled/com/mapswithme/maps/location/GoogleFusedLocationProvider.java @@ -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(); }); diff --git a/android/src/com/mapswithme/maps/location/BaseLocationProvider.java b/android/src/com/mapswithme/maps/location/BaseLocationProvider.java index 75bd571397..c43a0ac5e4 100644 --- a/android/src/com/mapswithme/maps/location/BaseLocationProvider.java +++ b/android/src/com/mapswithme/maps/location/BaseLocationProvider.java @@ -14,6 +14,8 @@ abstract class BaseLocationProvider @UiThread void onLocationChanged(@NonNull Location location); @UiThread + void onLocationResolutionRequired(@Nullable PendingIntent pendingIntent); + @UiThread void onLocationDisabled(); } diff --git a/android/src/com/mapswithme/maps/location/LocationHelper.java b/android/src/com/mapswithme/maps/location/LocationHelper.java index 9e71a0ec8d..517c1a3dd5 100644 --- a/android/src/com/mapswithme/maps/location/LocationHelper.java +++ b/android/src/com/mapswithme/maps/location/LocationHelper.java @@ -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, AppBackgroundTrack @Nullable private Dialog mLocationErrorDialog; @Nullable - ActivityResultLauncher mPermissionRequest; + private ActivityResultLauncher mPermissionRequest; + @Nullable + private ActivityResultLauncher mResolutionRequest; @SuppressWarnings("FieldCanBeLocal") private final LocationState.ModeChangeListener mMyPositionModeListener = @@ -307,6 +313,22 @@ public enum LocationHelper implements Initializable, 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, 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, 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, AppBackgroundTrack restart(); } + @UiThread + private void onLocationResolutionResult(int resultCode) + { + if (resultCode != Activity.RESULT_OK) + { + onLocationDisabled(); + return; + } + + restart(); + } + @UiThread public boolean isInFirstRun() {