Turn on location services without navigating to settings page

AndroidLocation

Android Problem Overview


Against the traditional approach of prompting user to go to the settings page and enable location services and come back again, I have noticed a simpler way of doing the same in some of the latest apps.

Referring to below screenshot, it prompts a dialog to user to enable the location services with just one click and it works in those apps.

How can I achieve the same?

enter image description here

Android Solutions


Solution 1 - Android

This dialog is created by LocationSettingsRequest.Builder available in the Google Play Services.

You need to add a dependency to your app build.gradle:

compile 'com.google.android.gms:play-services-location:10.0.1'

Then you can use this minimal example:

private void displayLocationSettingsRequest(Context context) {
    GoogleApiClient googleApiClient = new GoogleApiClient.Builder(context)
            .addApi(LocationServices.API).build();
    googleApiClient.connect();

    LocationRequest locationRequest = LocationRequest.create();
    locationRequest.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY);
    locationRequest.setInterval(10000);
    locationRequest.setFastestInterval(10000 / 2);

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

    PendingResult<LocationSettingsResult> result = LocationServices.SettingsApi.checkLocationSettings(googleApiClient, builder.build());
    result.setResultCallback(new ResultCallback<LocationSettingsResult>() {
        @Override
        public void onResult(LocationSettingsResult result) {
            final Status status = result.getStatus();
            switch (status.getStatusCode()) {
                case LocationSettingsStatusCodes.SUCCESS:
                    Log.i(TAG, "All location settings are satisfied.");
                    break;
                case LocationSettingsStatusCodes.RESOLUTION_REQUIRED:
                    Log.i(TAG, "Location settings are not satisfied. Show the user a dialog to upgrade location settings ");

                    try {
                        // Show the dialog by calling startResolutionForResult(), and check the result
                        // in onActivityResult().
                        status.startResolutionForResult(MainActivity.this, REQUEST_CHECK_SETTINGS);
                    } catch (IntentSender.SendIntentException e) {
                        Log.i(TAG, "PendingIntent unable to execute request.");
                    }
                    break;
                case LocationSettingsStatusCodes.SETTINGS_CHANGE_UNAVAILABLE:
                    Log.i(TAG, "Location settings are inadequate, and cannot be fixed here. Dialog not created.");
                    break;
            }
        }
    });
}

You can find the complete example here.

Solution 2 - Android

Follow the steps mentioned below

1) Create a LocationRequest as per your wish

LocationRequest mLocationRequest = LocationRequest.create()
           .setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY)
           .setInterval(10 * 1000)
           .setFastestInterval(1 * 1000);

2) Create a LocationSettingsRequest.Builder

LocationSettingsRequest.Builder settingsBuilder = new LocationSettingsRequest.Builder()
               .addLocationRequest(mLocationRequest);
settingsBuilder.setAlwaysShow(true);

3) Get LocationSettingsResponse Task using following code

Task<LocationSettingsResponse> result = LocationServices.getSettingsClient(this)
              .checkLocationSettings(settingsBuilder.build());

Note: LocationServices.SettingsApi is deprecated so, use SettingsClient Instead.

4) Add a OnCompleteListener to get the result from the Task.When the Task completes, the client can check the location settings by looking at the status code from the LocationSettingsResponse object.

result.addOnCompleteListener(new OnCompleteListener<LocationSettingsResponse>() {
    @Override
    public void onComplete(@NonNull Task<LocationSettingsResponse> task) {
    try {
        LocationSettingsResponse response = 
                          task.getResult(ApiException.class);
        } catch (ApiException ex) {
            switch (ex.getStatusCode()) {
                case LocationSettingsStatusCodes.RESOLUTION_REQUIRED:
                    try {
                        ResolvableApiException resolvableApiException = 
                                 (ResolvableApiException) ex;
                            resolvableApiException
                                   .startResolutionForResult(MapsActivity.this, 
                                         LOCATION_SETTINGS_REQUEST);
                    } catch (IntentSender.SendIntentException e) {

                    }
                    break;
                case LocationSettingsStatusCodes.SETTINGS_CHANGE_UNAVAILABLE:

                    break;
            }
        }
    }
});  

CASE 1: LocationSettingsStatusCodes.RESOLUTION_REQUIRED : Location is not enabled but, we can ask the user to enable the location by prompting him to turn on the location with the dialog (by calling startResolutionForResult).

Google Map Location Settings Request

CASE 2: LocationSettingsStatusCodes.SETTINGS_CHANGE_UNAVAILABLE : Location settings are not satisfied. However, we have no way to fix the settings so we won't show the dialog.

5) OnActivityResult we can get the user action in the location settings dialog. RESULT_OK => User turned on the Location. RESULT_CANCELLED - User declined the location setting request.

Solution 3 - Android

Its Working Similar to google maps

Add Dependency in build.gradle file

compile 'com.google.android.gms:play-services:8.3.0'

this or that

compile 'com.google.android.gms:play-services-location:10.0.1'

enter image description here

import android.content.Context;
import android.content.IntentSender;
import android.location.LocationManager;
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.util.Log;
import android.widget.Button;
import android.widget.TextView;
import android.widget.Toast;

import com.google.android.gms.common.ConnectionResult;
import com.google.android.gms.common.api.GoogleApiClient;
import com.google.android.gms.common.api.PendingResult;
import com.google.android.gms.common.api.ResultCallback;
import com.google.android.gms.common.api.Status;
import com.google.android.gms.location.LocationRequest;
import com.google.android.gms.location.LocationServices;
import com.google.android.gms.location.LocationSettingsRequest;
import com.google.android.gms.location.LocationSettingsResult;
import com.google.android.gms.location.LocationSettingsStatusCodes;

import java.util.List;

public class LocationOnOff_Similar_To_Google_Maps extends AppCompatActivity {

    protected static final String TAG = "LocationOnOff";

    private GoogleApiClient googleApiClient;
    final static int REQUEST_LOCATION = 199;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        this.setFinishOnTouchOutside(true);

        // Todo Location Already on  ... start
        final LocationManager manager = (LocationManager) LocationOnOff_Similar_To_Google_Maps.this.getSystemService(Context.LOCATION_SERVICE);
        if (manager.isProviderEnabled(LocationManager.GPS_PROVIDER) && hasGPSDevice(LocationOnOff_Similar_To_Google_Maps.this)) {
            Toast.makeText(LocationOnOff_Similar_To_Google_Maps.this,"Gps already enabled",Toast.LENGTH_SHORT).show();
            finish();
        }
        // Todo Location Already on  ... end

        if(!hasGPSDevice(LocationOnOff_Similar_To_Google_Maps.this)){
            Toast.makeText(LocationOnOff_Similar_To_Google_Maps.this,"Gps not Supported",Toast.LENGTH_SHORT).show();
        }

        if (!manager.isProviderEnabled(LocationManager.GPS_PROVIDER) && hasGPSDevice(LocationOnOff_Similar_To_Google_Maps.this)) {
            Log.e("keshav","Gps already enabled");
            Toast.makeText(LocationOnOff_Similar_To_Google_Maps.this,"Gps not enabled",Toast.LENGTH_SHORT).show();
            enableLoc();
        }else{
            Log.e("keshav","Gps already enabled");
            Toast.makeText(LocationOnOff_Similar_To_Google_Maps.this,"Gps already enabled",Toast.LENGTH_SHORT).show();
        }
    }


    private boolean hasGPSDevice(Context context) {
        final LocationManager mgr = (LocationManager) context
                .getSystemService(Context.LOCATION_SERVICE);
        if (mgr == null)
            return false;
        final List<String> providers = mgr.getAllProviders();
        if (providers == null)
            return false;
        return providers.contains(LocationManager.GPS_PROVIDER);
    }

    private void enableLoc() {

        if (googleApiClient == null) {
            googleApiClient = new GoogleApiClient.Builder(LocationOnOff_Similar_To_Google_Maps.this)
                    .addApi(LocationServices.API)
                    .addConnectionCallbacks(new GoogleApiClient.ConnectionCallbacks() {
                        @Override
                        public void onConnected(Bundle bundle) {

                        }

                        @Override
                        public void onConnectionSuspended(int i) {
                            googleApiClient.connect();
                        }
                    })
                    .addOnConnectionFailedListener(new GoogleApiClient.OnConnectionFailedListener() {
                        @Override
                        public void onConnectionFailed(ConnectionResult connectionResult) {

                            Log.d("Location error","Location error " + connectionResult.getErrorCode());
                        }
                    }).build();
            googleApiClient.connect();

            LocationRequest locationRequest = LocationRequest.create();
            locationRequest.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY);
            locationRequest.setInterval(30 * 1000);
            locationRequest.setFastestInterval(5 * 1000);
            LocationSettingsRequest.Builder builder = new LocationSettingsRequest.Builder()
                    .addLocationRequest(locationRequest);

            builder.setAlwaysShow(true);

            PendingResult<LocationSettingsResult> result =
                    LocationServices.SettingsApi.checkLocationSettings(googleApiClient, builder.build());
            result.setResultCallback(new ResultCallback<LocationSettingsResult>() {
                @Override
                public void onResult(LocationSettingsResult result) {
                    final Status status = result.getStatus();
                    switch (status.getStatusCode()) {
                        case LocationSettingsStatusCodes.RESOLUTION_REQUIRED:
                            try {
                                // Show the dialog by calling startResolutionForResult(),
                                // and check the result in onActivityResult().
                                status.startResolutionForResult(LocationOnOff_Similar_To_Google_Maps.this, REQUEST_LOCATION);

                                finish();
                            } catch (IntentSender.SendIntentException e) {
                                // Ignore the error.
                            }
                            break;
                    }
                }
            });
        }
    }

}

Solution 4 - Android

implementation 'com.google.android.gms:play-services-location:16.0.0'

Variable Declaration

private SettingsClient mSettingsClient;
private LocationSettingsRequest mLocationSettingsRequest;
private static final int REQUEST_CHECK_SETTINGS = 214;
private static final int REQUEST_ENABLE_GPS = 516;

Open Dialog Using Below Code

LocationSettingsRequest.Builder builder = new LocationSettingsRequest.Builder();
builder.addLocationRequest(new LocationRequest().setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY));
builder.setAlwaysShow(true);
mLocationSettingsRequest = builder.build();

mSettingsClient = LocationServices.getSettingsClient(YourActivity.this);

mSettingsClient
	.checkLocationSettings(mLocationSettingsRequest)
	.addOnSuccessListener(new OnSuccessListener<LocationSettingsResponse>() {
		@Override
		public void onSuccess(LocationSettingsResponse locationSettingsResponse) {
			//Success Perform Task Here
		}
	})
	.addOnFailureListener(new OnFailureListener() {
		@Override
		public void onFailure(@NonNull Exception e) {
			int statusCode = ((ApiException) e).getStatusCode();
			switch (statusCode) {
				case LocationSettingsStatusCodes.RESOLUTION_REQUIRED:
					try {
						ResolvableApiException rae = (ResolvableApiException) e;
						rae.startResolutionForResult(YourActivity.this, REQUEST_CHECK_SETTINGS);
					} catch (IntentSender.SendIntentException sie) {
						Log.e("GPS","Unable to execute request.");
					}
					break;
				case LocationSettingsStatusCodes.SETTINGS_CHANGE_UNAVAILABLE:
					Log.e("GPS","Location settings are inadequate, and cannot be fixed here. Fix in Settings.");
			}
		}
	})
	.addOnCanceledListener(new OnCanceledListener() {
		@Override
		public void onCanceled() {
			Log.e("GPS","checkLocationSettings -> onCanceled");
		}
	});

onActivityResult

@Override
public void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) {
	super.onActivityResult(requestCode, resultCode, data);

	if (requestCode == REQUEST_CHECK_SETTINGS) {
		switch (resultCode) {
			case Activity.RESULT_OK:
				//Success Perform Task Here
				break;
			case Activity.RESULT_CANCELED:
				Log.e("GPS","User denied to access location");
				openGpsEnableSetting();
				break;
		}
	} else if (requestCode == REQUEST_ENABLE_GPS) {
		LocationManager locationManager = (LocationManager) getSystemService(Context.LOCATION_SERVICE);
		boolean isGpsEnabled = locationManager.isProviderEnabled(LocationManager.GPS_PROVIDER);

		if (!isGpsEnabled) {
			openGpsEnableSetting();
		} else {
			navigateToUser();
		}
	}
}

private void openGpsEnableSetting() {
	Intent intent = new Intent(Settings.ACTION_LOCATION_SOURCE_SETTINGS);
	startActivityForResult(intent, REQUEST_ENABLE_GPS);
}	

		

Solution 5 - Android

Thanks to Mattia Maestrini +1

Xamarin solution:

using Android.Gms.Common.Apis;
using Android.Gms.Location;

public const int REQUEST_CHECK_SETTINGS = 0x1;

private void DisplayLocationSettingsRequest()
{
    var googleApiClient = new GoogleApiClient.Builder(this).AddApi(LocationServices.API).Build();
    googleApiClient.Connect();

    var locationRequest = LocationRequest.Create();
    locationRequest.SetPriority(LocationRequest.PriorityHighAccuracy);
    locationRequest.SetInterval(10000);
    locationRequest.SetFastestInterval(10000 / 2);

    var builder = new LocationSettingsRequest.Builder().AddLocationRequest(locationRequest);
    builder.SetAlwaysShow(true);

    var result = LocationServices.SettingsApi.CheckLocationSettings(googleApiClient, builder.Build());
    result.SetResultCallback((LocationSettingsResult callback) =>
    {
        switch (callback.Status.StatusCode)
        {
            case LocationSettingsStatusCodes.Success:
                {
                    DoStuffWithLocation();
                    break;
                }
            case LocationSettingsStatusCodes.ResolutionRequired:
                {
                    try
                    {
                        // Show the dialog by calling startResolutionForResult(), and check the result
                        // in onActivityResult().
                        callback.Status.StartResolutionForResult(this, REQUEST_CHECK_SETTINGS);
                    }
                    catch (IntentSender.SendIntentException e)
                    {
                    }

                    break;
                }
            default:
                {
                    // If all else fails, take the user to the android location settings
                    StartActivity(new Intent(Android.Provider.Settings.ActionLocationSourceSettings));
                    break;
                }
        }
    });
}

protected override void OnActivityResult(int requestCode, Android.App.Result resultCode, Intent data)
{
    switch (requestCode)
    {
        case REQUEST_CHECK_SETTINGS:
            {
                switch (resultCode)
                {
                    case Android.App.Result.Ok:
                        {
                            DoStuffWithLocation();
                            break;
                        }
                    case Android.App.Result.Canceled:
                        {
                            //No location
                            break;
                        }
                }
                break;
            }
    }
}

NOTE:

This will not work with Huawei or other devices which does not have google services installed.

Solution 6 - Android

Kotlin Solution

Add build.gradle(Module:app)

implementation 'com.google.android.gms:play-services-location:17.0.0'
implementation 'com.google.android.gms:play-services-maps:17.0.0'

after that create this function

fun enablegps() {

    val mLocationRequest = LocationRequest.create()
        .setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY)
        .setInterval(2000)
        .setFastestInterval(1000)

    val settingsBuilder = LocationSettingsRequest.Builder()
        .addLocationRequest(mLocationRequest)
    settingsBuilder.setAlwaysShow(true)

    val result = LocationServices.getSettingsClient(this).checkLocationSettings(settingsBuilder.build())
    result.addOnCompleteListener { task ->

        //getting the status code from exception
        try {
            task.getResult(ApiException::class.java)
        } catch (ex: ApiException) {

            when (ex.statusCode) {

                LocationSettingsStatusCodes.RESOLUTION_REQUIRED -> try {

                    Toast.makeText(this,"GPS IS OFF",Toast.LENGTH_SHORT).show()

                    // Show the dialog by calling startResolutionForResult(), and check the result
                    // in onActivityResult().
                    val resolvableApiException = ex as ResolvableApiException
                    resolvableApiException.startResolutionForResult(this,REQUEST_CHECK_SETTINGS
                    )
                } catch (e: IntentSender.SendIntentException) {
                    Toast.makeText(this,"PendingIntent unable to execute request.",Toast.LENGTH_SHORT).show()

                }

                LocationSettingsStatusCodes.SETTINGS_CHANGE_UNAVAILABLE -> {

                    Toast.makeText(
                        this,
                        "Something is wrong in your GPS",
                        Toast.LENGTH_SHORT
                    ).show()

                }


            }
        }



    }


}

Solution 7 - Android

Android Marshmallow 6 supports runtime permission. Runtime permissions only work on Marshmallow and on pre-Marshmallow it still works the old way.

You can learn more about it in this Android Developer official Video:

https://www.youtube.com/watch?v=C8lUdPVSzDk

And requesting permission: http://developer.android.com/training/permissions/requesting.html

Solution 8 - Android

Thank you Mattia Maestrini for the Answer, I would like to add that using

compile 'com.google.android.gms:play-services-location:8.1.0'

would suffice. This prevents your app including unnecessary libraries and helps for keeping your method count low.

Solution 9 - Android

With recent Marshmallow update, even when the Location setting is turned on, your app will require to explicitly ask for permission. The recommended way to do this is to show the Permissions section of your app wherein the user can toggle the permission as required. The code snippet for doing this is as below:

if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
    
	if (this.checkSelfPermission(Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
    
		final AlertDialog.Builder builder = new AlertDialog.Builder(this);
		builder.setTitle("Location Permission");
		builder.setMessage("The app needs location permissions. Please grant this permission to continue using the features of the app.");
		builder.setPositiveButton(android.R.string.yes, new DialogInterface.OnClickListener() {
            @Override
            public void onClick(DialogInterface dialogInterface, int i) {
                requestPermissions(new String[]{Manifest.permission.ACCESS_COARSE_LOCATION}, PERMISSION_REQUEST_COARSE_LOCATION);
    
            }
        });
        builder.setNegativeButton(android.R.string.no, null);
        builder.show();
    }
} else {
	// do programatically as show in the other answer 
}

And override the onRequestPermissionsResult method as below:

@Override
public void onRequestPermissionsResult(int requestCode, String permissions[], int[] grantResults) {
        switch (requestCode) {
            case PERMISSION_REQUEST_COARSE_LOCATION: {
                if (grantResults[0] == PackageManager.PERMISSION_GRANTED) {
                    Log.d(TAG, "coarse location permission granted");
                } else {
                    Intent intent = new Intent();
                    intent.setAction(Settings.ACTION_APPLICATION_DETAILS_SETTINGS);
                    Uri uri = Uri.fromParts("package", getPackageName(), null);
                    intent.setData(uri);
                    startActivity(intent);
                }
            }
        }
    }

Another approach is you can also use the SettingsApi to inquire which location provider(s) are enabled. If none is enabled, you can prompt a dialog to change the setting from within the app.

Solution 10 - Android

If you want to replace deprecated onActivityResult and startResolutionForResult in Fragment, see https://stackoverflow.com/a/65816646/2914140.

val checkLocationSettings = 
    registerForActivityResult(ActivityResultContracts.StartIntentSenderForResult()) { result ->
        if (result.resultCode == RESULT_OK) {
            // GPS is turned on in system settings.
        }
}

...

val intentSenderRequest = IntentSenderRequest.Builder(resolvable.resolution).build()
checkLocationSettings.launch(intentSenderRequest)

Solution 11 - Android

The simplest way I found while my research, is to create a Util class for this location requesting process and then call it to turn the gps ON for us.

Please check this blog! It told the whole story.

Solution 12 - Android

 private void openDeviceLocationRequest() {
        if (!locationPermissionGranted)
            return;

        LocationRequest locationRequest = LocationRequest.create();
        locationRequest.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY);
        LocationSettingsRequest.Builder builder = new LocationSettingsRequest.Builder()
                .addLocationRequest(locationRequest);
        builder.setAlwaysShow(true); //this is the key ingredient

        Task<LocationSettingsResponse> result =
                LocationServices.getSettingsClient(this).checkLocationSettings(builder.build());
        result.addOnCompleteListener(task -> {
            try {
                LocationSettingsResponse response = task.getResult(ApiException.class);
                // All location settings are satisfied. The client can initialize location
                // requests here.
                if(lastKnownLocation == null)
                getDeviceLocation();

            } catch (ApiException exception) {
                switch (exception.getStatusCode()) {
                    case LocationSettingsStatusCodes.RESOLUTION_REQUIRED:
                        // Location settings are not satisfied. But could be fixed by showing the
                        // user a dialog.
                        try {
                            // Cast to a resolvable exception.
                            ResolvableApiException resolvable = (ResolvableApiException) exception;
                            // Show the dialog by calling startResolutionForResult(),
                            // and check the result in onActivityResult().
                            resolvable.startResolutionForResult(
                                    MapAddressActivity.this,
                                    REQUEST_CHECK_SETTINGS);
                        } catch (IntentSender.SendIntentException e) {
                            // Ignore the error.
                        } catch (ClassCastException e) {
                            // Ignore, should be an impossible error.
                        }
                        break;
                    case LocationSettingsStatusCodes.SETTINGS_CHANGE_UNAVAILABLE:
                        // Location settings are not satisfied. However, we have no way to fix the
                        // settings so we won't show the dialog.
                        break;
                }
            }
        });
    }

Solution 13 - Android

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate( savedInstanceState );
    setContentView( R.layout.activity_main );        

    LocationManager manager = (LocationManager) getSystemService( Context.LOCATION_SERVICE );
    if (!manager.isProviderEnabled( LocationManager.GPS_PROVIDER )) {
        buildAlertMessageNoGps();
    }
}
private void buildAlertMessageNoGps() {
    final AlertDialog.Builder builder = new AlertDialog.Builder( this );
    builder.setMessage( "Your GPS seems to be disabled, do you want to enable it?" )
            .setCancelable( false )
            .setPositiveButton( "Yes", (dialog, id) -> startActivity( new Intent( android.provider.Settings.ACTION_LOCATION_SOURCE_SETTINGS ) ) )
            .setNegativeButton( "No", (dialog, id) -> dialog.cancel() );
    final AlertDialog alert = builder.create();
    alert.show();
}

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionGAMAView Question on Stackoverflow
Solution 1 - AndroidMattia MaestriniView Answer on Stackoverflow
Solution 2 - AndroidRevanthKrishnaKumar V.View Answer on Stackoverflow
Solution 3 - AndroidKeshav GeraView Answer on Stackoverflow
Solution 4 - AndroidKetan RamaniView Answer on Stackoverflow
Solution 5 - AndroidPierreView Answer on Stackoverflow
Solution 6 - AndroidJimale AbdiView Answer on Stackoverflow
Solution 7 - AndroidSharjeelView Answer on Stackoverflow
Solution 8 - AndroidVuong PhamView Answer on Stackoverflow
Solution 9 - AndroidMahendra LiyaView Answer on Stackoverflow
Solution 10 - AndroidCoolMindView Answer on Stackoverflow
Solution 11 - AndroidHarpreetView Answer on Stackoverflow
Solution 12 - AndroidYasin EgeView Answer on Stackoverflow
Solution 13 - AndroidMayank PanchalView Answer on Stackoverflow