How to correctly prompt a user to turn on "Improve Location Accuracy" setting?

Viewed 773

My application requires that the user have Improved Location Accuracy turned on in their settings. Unfortunately, I can't figure out the correct way to actually get to the right menu, and have the back button return to my application once the setting is set.

Here is what I have:

    private fun checkLocationSettingsAsync() {
        viewModel.launch(Dispatchers.IO) {
            val locationSettings = client.checkLocationSettings(
                locationBuilder.build()
            ).asDeferred()

            locationSettings.asTask().addOnSuccessListener {
                //location settings are already high accuracy
                locationSettingsOkay = true
            }.addOnFailureListener { e ->
                if (e is ResolvableApiException) {
                    //location settings not satisfied, request to make them higher
                    runCatching {
                        val intent = Intent(android.provider.Settings.ACTION_LOCATION_SOURCE_SETTINGS)
                        startActivityForResult(intent, LOCATION_ACCURACY_ACCESS_CODE)
                    }.onFailure {
                        println(it.stackTrace)
                    }
                }
            }

            locationSettings.await()
        }
    }

    override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
        super.onActivityResult(requestCode, resultCode, data)
        when (requestCode) {
            LOCATION_ACCURACY_ACCESS_CODE -> {
                if (resultCode == Activity.RESULT_OK) {
                    //TODO: navigate back to activity once setting is set
                }
            }
        }
    }

The Android menu Settings.ACTION_LOCATION_SOURCE_SETTINGS gets to the outer menu that contains the Improved Location Accuracy setting, but I can't actually find the correct Intent name to get to the appropriate menu, nor can I get it so that the user can navigate back to my application when the setting is enabled.

Any advice? Or documentation, since I can't find anything about this!

EDIT: here is a good code sample! https://github.com/googlesamples/android-play-location/blob/master/LocationUpdates/app/src/main/java/com/google/android/gms/location/sample/locationupdates/MainActivity.java

4 Answers

Below code is used to Prompt the user to change location settings Click here to see full document

task.addOnSuccessListener { locationSettingsResponse ->
   // All location settings are satisfied. The client can initialize
   // location requests here.    
}
task.addOnFailureListener { exception ->
 if (exception is ResolvableApiException){
     // Location settings are not satisfied, but this can be fixed
     // by showing the user a dialog.
     try {
         // Show the dialog by calling startResolutionForResult(),
         // and check the result in onActivityResult().
         exception.startResolutionForResult(this@MainActivity,
                 REQUEST_CHECK_SETTINGS)
     } catch (sendEx: IntentSender.SendIntentException) {
         // Ignore the error.
     }
 }
}

Here's How I do It

Gps Settings are Not okay ?

  1. Show User "Turn On Gps Dialog" using

From Activity :

status.startResolutionForResult(this , REQUEST_CHECK_SETTINGS);

From Fragment:

startIntentSenderForResult(status.getResolution().getIntentSender(), REQUEST_CHECK_SETTINGS, null, 0, 0, 0, null)
  1. Look For Results In onActivityResult

If You Are Requesting HIGH_ACCURACY upgrades Beware Of This bug

Not Able To Upgrade Gps settings to high Accuracy using FusedLocationProvider In some devices

Although I haven't encountered this bug after last update of Google Play Services.....but I am not sure if this bug has been fixed completely or not

if resultCode is RESULT_OK -> do nothing

if resultCode is RESULT_CANCELED -> Show User A Dialog that he will need to upgrade Gps Priority Manually and redirect user to location Settings Page using

Intent intent = new Intent(Settings.ACTION_LOCATION_SOURCE_SETTINGS);
startActivityForResult(intent, REQUEST_UPDATE_GPS_SETTINGS_MANUALLY);

This might help you out :

Sorry if it's in java. let me know if it's work.

 public static void displayPromptForEnablingGPS(final Activity activity, Context context) {
        LocationManager lm = (LocationManager) activity.getSystemService(LOCATION_SERVICE);
        if (!lm.isProviderEnabled(LocationManager.GPS_PROVIDER) ||
                !lm.isProviderEnabled(LocationManager.NETWORK_PROVIDER)) {

            AlertDialog.Builder builder = new AlertDialog.Builder(context);
            builder.setTitle(R.string.locationTitle);
            builder.setMessage(R.string.enableLocation);
            builder.setPositiveButton(R.string.OK, new DialogInterface.OnClickListener() {
                public void onClick(DialogInterface dialogInterface, int i) {

                    Intent intent = new Intent(Settings.ACTION_LOCATION_SOURCE_SETTINGS);
                    activity.startActivity(intent);
                }
            });
            Dialog alertDialog = builder.create();
            alertDialog.setCanceledOnTouchOutside(false);
            alertDialog.show();
        }
    }

Here is the solution I came up with after realizing that I needed to use startIntentSenderForResult instead of startResolutionForResult because I was launching it from a fragment. :-)

    private fun checkLocationSettings() {
        settingsClient.checkLocationSettings(locationSettingsRequest).addOnSuccessListener {
            //all settings satisfied!
            locationSettingsOkay = true
        }.addOnFailureListener { e ->
            val statusCode = (e as ApiException).statusCode
            when (statusCode) {
                LocationSettingsStatusCodes.RESOLUTION_REQUIRED -> {
                    println("settings not good enough, attempting to upgrade them")
                    try {
                        val rae = (e as ResolvableApiException)
                        startIntentSenderForResult(
                            rae.resolution.intentSender,
                            REQUEST_CHECK_SETTINGS,
                            null, 0, 0, 0, null
                            )
                    } catch (sie : IntentSender.SendIntentException) {
                        println("pending intent unable to process request")
                    }
                }
                LocationSettingsStatusCodes.SETTINGS_CHANGE_UNAVAILABLE -> {
                    Toast.makeText(
                        this@PrimerFrag.requireContext(),
                        "Location settings can't be fixed here. Try to turn on Improved Location Accuracy in settings.",
                        Toast.LENGTH_LONG
                        ).show()
                }
            }
        }
    }

    override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
        when (requestCode) {
            REQUEST_CHECK_SETTINGS -> {
                when (resultCode) {
                    Activity.RESULT_OK -> {
                        locationSettingsOkay = true
                        if (locationPermissionGranted && resultSuccess) {
                            makeButtonsReadyAndSubmitList(resultList, destinationsAdapter)
                        }
                    }
                    Activity.RESULT_CANCELED -> {
                        //TODO: ask for location settings again
                    }
                }
            }
        }
    }

Related