138

I use the latest version of Google Play Services (7.0) and followed the steps given in their guide and I enabled the location dialog like below, which has a "never" button. My app needs location mandatorily so I don't want to show "never" to user, because once the user clicks "never", I'm unable to get location or request for location again at all.

Where as Google Maps has only yes and no button without never button, any idea how to achieve the same?

My app's image enter image description here

Google Map's image enter image description here

MMG
  • 3,226
  • 5
  • 16
  • 43
Mufri A
  • 1,395
  • 2
  • 9
  • 7
  • Here is my solution for kotlin users: https://stackoverflow.com/questions/31235564/locationsettingsrequest-dialog-to-enable-gps-onactivityresult-skipped/68359749#68359749 – Shoaib Kakal Jul 13 '21 at 10:57

13 Answers13

151

LocationSettingsRequest.Builder has a method setAlwaysShow(boolean show). While the document indicates it's currently doing nothing(updated 2015-07-05: updated Google documentation has removed this wording), setting builder.setAlwaysShow(true); will enable Google Maps behavior: enter image description here

Here's the code that got it working:

if (googleApiClient == null) {
    googleApiClient = new GoogleApiClient.Builder(getActivity())
            .addApi(LocationServices.API)
            .addConnectionCallbacks(this)
            .addOnConnectionFailedListener(this).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); //this is the key ingredient
    //**************************

    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();
            final LocationSettingsStates state = result.getLocationSettingsStates();
            switch (status.getStatusCode()) {
                case LocationSettingsStatusCodes.SUCCESS:
                    // All location settings are satisfied. The client can initialize location
                    // requests here.
                    break;
                case LocationSettingsStatusCodes.RESOLUTION_REQUIRED:
                    // Location settings are not satisfied. But could be fixed by showing the user
                    // a dialog.
                    try {
                        // Show the dialog by calling startResolutionForResult(),
                        // and check the result in onActivityResult().
                        status.startResolutionForResult(
                                getActivity(), 1000);
                    } catch (IntentSender.SendIntentException e) {
                        // Ignore the 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;
            }
        }
    });
}

From Android Documentation

For Kotlin see here: https://stackoverflow.com/a/61868985/12478830

MMG
  • 3,226
  • 5
  • 16
  • 43
Kai
  • 15,284
  • 6
  • 51
  • 82
  • Hi Kai, can you show the complete logic, with its callbacks along with its implementation. I have tried this in Fragment class extending Map Class from Google. But i am getting Null Pointer result on PendingResults Array. Can you please guide? – Ravi Kabra May 23 '15 at 07:20
  • The code above _is_ the complete logic. The question is "How to show enable location dialog like Google maps?", but it appears your question is more about using embedded Google Maps, which is another question entirely. Please start a new question and I can try to answer (no promises though since I've never actually used embedded Google Maps) – Kai May 24 '15 at 01:49
  • You don't wait for the googleApiClient.connect(); to connect, do you? – Marian Paździoch Jun 23 '15 at 09:36
  • 1
    @MarianPaździoch pretty sure you don't need to, since Google's own sample code on SettingsApi doesn't require it. – Kai Jun 23 '15 at 10:32
  • Anyway in docs there is: "It does not need to be connected at the time of this call, but the result will be delayed until the connection is complete." – Marian Paździoch Jun 23 '15 at 10:44
  • @Kai When I implement this code, pressing "No" on the dialog or pressing the native back button will not dismiss the dialog. It will continue showing the dialog until I either press "Yes" to enable location services, or close and re-open the app. Any idea how to fix that? – pez Jul 04 '15 at 17:47
  • @pez never encountered this myself, are you running the code unmodified, and does it happen on all your devices? – Kai Jul 05 '15 at 03:21
  • 2
    @Kai Yes, the code is unmodified on a Nexus 5. Using Logs, I see that when location services are initially off, it always hits `RESOLUTION_REQUIRED`. Then once I accept and enable location, it hits `SUCCESS`, and entirely skips `onActivityResult()`. Pressing `No` or back makes the dialog disappear for a second, then reload and hit `RESOLUTION_REQUIRED` again. The only way to get rid of the dialog is to either accept, or close and re-open the app. – pez Jul 05 '15 at 03:35
  • 2
    @pez tested on Galaxy S4 with Google Play services 7.5.74 and it works, canceling doesn't cause RESOLUTION_REQUIRED to be called. My suggestion would be to update play services and try again. If that failed, start a new StackOverflow question to see if others have encountered and solved this issue. – Kai Jul 05 '15 at 04:17
  • 2
    @Kai it worked for me but what if a user pressed no.How to show the dialog again or add some code there if pressed no.Any help will be highly appreciated. – Gurpreet singh Oct 10 '15 at 08:25
  • @Kai I want to show this dialog on button click,Is it possible to do? I tried but its not working. – Nitish Jan 11 '16 at 14:18
  • Should i use google map api key for this.i am using this code but no dialogue is showing.i am getting this error in logcat..GoogleService failed to initialize, status: 10, Missing an expected resource: 'R.string.google_app_id' for initializing Google services. Possible causes are missing google-services.json or com.google.gms.google-services gradle plugin. – Muhammad Waleed Jan 15 '16 at 12:30
  • @ExceptionLover no Google map API key is not required, since you are simply asking Google Play service to perform the changes for you. Your issue seem to be [this](http://stackoverflow.com/questions/34365369/googleservice-failed-to-initialize). – Kai Jan 17 '16 at 12:42
  • @Nitish Assuming the status code is `LocationSettingsStatusCodes.RESOLUTION_REQUIRED`, you should be able to cache the `status` object and only call `status.startResolutionForResult(getActivity(), 1000);` on button click. If this is what you did and isn't working then I'd need more info, maybe start a new question if the info you'd need to provide is long. – Kai Jan 17 '16 at 12:46
  • I'm a bit confused. I displayed a map for my app and I even requested the Fine Location permissions without having a GoogleApiClient at all. However, when I click on the MyLocation button on the map nothing used to happen when you haven't turned on your location on the phone so I wanted to show this dialog. Why do I need to connect to the API just for that setting change? – iBobb Mar 21 '16 at 18:19
  • @iBobb If the location setting of the phone is off, you don't get any location (it's off, remember?). To check for location setting you can either write your own code or use Google API as above, which is easier. – Kai Mar 22 '16 at 01:10
  • Okay thank you, another quick thing then, so is it possible to seemlessly stop the high accuracy the user allowed for us to use after the application is closed for example, so that the user doesn't have to stop it himself? Or can we use this high accuracy location without updating location based on frequency? what if we just need to know the current location once? – iBobb Mar 22 '16 at 02:01
  • 1
    NOTE: your activity's `launchMode` can NOT be set to `singleInstance` otherwise this will NOT work. The dialog will never show up and `onActivityResult` will be called automatically. DO NOT HAVE `android:launchMode="singleInstance"` for your activity in `AndroidManifest`. I learned this very hard way after 3 hours – ᴛʜᴇᴘᴀᴛᴇʟ Oct 09 '16 at 04:52
  • hai can i customize dialog color? – learner Dec 07 '16 at 05:23
  • I would like to add here after the comment from th3patel. That if your activity has `android:clearTaskOnLaunch="true"` Then dialog will never show.. – Sharp Edge Feb 08 '17 at 23:31
  • After changing `LocationRequest` priority from `PRIORITY_LOW_POWER` to `PRIORITY_HIGH_ACCURACY`, the dialog finally showed up. It just took me 5 hours to realize this. Perhaps, Google might want to consider to put some notes about this one? – mr5 Mar 27 '17 at 10:26
  • This is asking for wifi/background scanning on my phone as well. Is there a way for it to just be GPS + data only? – lawonga Apr 15 '17 at 22:45
  • Hello, I have a issue, when I turn on GPS and try to load data second time, The map is not zooming at its particular location. Will anybody pls. see here : https://stackoverflow.com/questions/44368960/issue-with-updating-googlemap-by-doing-gps-on-off – Jaimin Modi Jun 06 '17 at 06:48
  • why on screenshot it says only "**GPS use for location**" when it should "**GPS, Wi-Fi and mobile for locaiton**" if you set `LocationRequest.PRIORITY_HIGH_ACCURACY`?? – user924 Jan 15 '18 at 14:03
  • @user924 that's the wording they used 2.5 years ago, may or may not be the same now – Kai Jan 16 '18 at 00:22
  • Can I somehow change the text in that dialog? Or use my own dialog? – Hayk Mkrtchyan Nov 14 '19 at 19:55
  • add wrong tag `supportlifecyclefragmentimpl` using this dialog. – Kishan Viramgama Jan 29 '20 at 09:39
  • how to handle "YES" and "NO" button click call back ? – Gyan Swaroop Awasthi Jul 23 '21 at 07:20
55

I would like to add up some changes to kai's answer for those who are looking for handling Yes/No buttons.

Declare this constant in your activity

protected static final int REQUEST_CHECK_SETTINGS = 0x1;

call settingsrequest() in your onStart()

public void settingsrequest()
    {
        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); //this is the key ingredient

        PendingResult<LocationSettingsResult> result =
                LocationServices.SettingsApi.checkLocationSettings(mGoogleApiClient, builder.build());
        result.setResultCallback(new ResultCallback<LocationSettingsResult>() {
            @Override
            public void onResult(LocationSettingsResult result) {
                final Status status = result.getStatus();
                final LocationSettingsStates state = result.getLocationSettingsStates();
                switch (status.getStatusCode()) {
                    case LocationSettingsStatusCodes.SUCCESS:
                        // All location settings are satisfied. The client can initialize location
                        // requests here.
                        break;
                    case LocationSettingsStatusCodes.RESOLUTION_REQUIRED:
                        // Location settings are not satisfied. But could be fixed by showing the user
                        // a dialog.
                        try {
                            // Show the dialog by calling startResolutionForResult(),
                            // and check the result in onActivityResult().
                            status.startResolutionForResult(MainActivity.this, REQUEST_CHECK_SETTINGS);
                        } catch (IntentSender.SendIntentException e) {
                            // Ignore the 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;
                }
            }
        });
    }
    @Override
    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
        switch (requestCode) {
// Check for the integer request code originally supplied to startResolutionForResult().
            case REQUEST_CHECK_SETTINGS:
                switch (resultCode) {
                    case Activity.RESULT_OK:
                        startLocationUpdates();
                        break;
                    case Activity.RESULT_CANCELED:
                        settingsrequest();//keep asking if imp or do whatever
                        break;
                }
                break;
        }
    }
Parag Chauhan
  • 35,760
  • 13
  • 86
  • 95
Veer3383
  • 1,785
  • 6
  • 29
  • 49
  • 1
    got from the official documentation: https://developers.google.com/android/reference/com/google/android/gms/location/SettingsApi if you need to add only maps, to use this you have to add those libraries (without importing the entire play services library): compile 'com.google.android.gms:play-services-maps:9.0.2' compile 'com.google.android.gms:play-services-location:9.0.2' – MatPag Jun 27 '16 at 13:54
  • how to handle click event of this dialog and i must never show never button in dialog – M.Yogeshwaran Oct 20 '16 at 09:40
  • remove the settingsrequest() line from switch case in ActivityOnResult.. Is that what you are asking??? – Veer3383 Oct 20 '16 at 10:44
  • If I click on no button of dialog still that dialog comes continuously.. I already remove the settingsrequest() line from switch case in ActivityOnResult.. then why it is showing continuously? – Asmi Nov 03 '16 at 10:27
  • May be u need to clean build the project. – Veer3383 Nov 03 '16 at 11:32
  • Which class is `builder` came from? – mr5 Mar 27 '17 at 03:44
  • Builder is Implemented as Inner class of LocationSettingsRequest class, refer to the Documentation for more details : https://developers.google.com/android/reference/com/google/android/gms/location/SettingsApi – Veer3383 Mar 27 '17 at 04:49
  • Hello, I have a issue, when I turn on GPS and try to load data second time, The map is not zooming at its particular location. Will anybody pls. see here : https://stackoverflow.com/questions/44368960/issue-with-updating-googlemap-by-doing-gps-on-off – Jaimin Modi Jun 06 '17 at 06:48
  • i think there is problem in your answer, you did not build GoogleApiClient – Dhruv Tyagi Jun 08 '17 at 11:10
  • @DhruvTyagi my answer only aims at handling the dialog buttons if the users chooses not to share the location. building the GoogleApiClient is the pre requisite for this. – Veer3383 Jun 12 '17 at 09:46
28

LocationServices.SettingsApi is deprecated now, So We use SettingsClient

    LocationRequest mLocationRequest = new LocationRequest();
        mLocationRequest.setInterval(10);
        mLocationRequest.setSmallestDisplacement(10);
        mLocationRequest.setFastestInterval(10);
        mLocationRequest.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY);
        LocationSettingsRequest.Builder builder = new 
        LocationSettingsRequest.Builder();
        builder.addLocationRequest(mLocationRequest);

Then check whether current location settings are satisfied. Create the LocationSettingsResponse task:

        Task<LocationSettingsResponse> task=LocationServices.getSettingsClient(this).checkLocationSettings(builder.build());

Then add Listener

task.addOnCompleteListener(new OnCompleteListener<LocationSettingsResponse>() {
            @Override
                    public void onComplete(Task<LocationSettingsResponse> task) {
                        try {
                            LocationSettingsResponse response = task.getResult(ApiException.class);
                            // All location settings are satisfied. The client can initialize location
                            // requests here.

                        } 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(
                                                HomeActivity.this,
                                                101);
                                    } 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;
                            }
                        }
                    }
                });

Added onActivityResult

@Override
    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
        final LocationSettingsStates states = LocationSettingsStates.fromIntent(data);
        switch (requestCode) {
            case 101:
                switch (resultCode) {
                    case Activity.RESULT_OK:
                        // All required changes were successfully made
                        Toast.makeText(HomeActivity.this,states.isLocationPresent()+"",Toast.LENGTH_SHORT).show();
                        break;
                    case Activity.RESULT_CANCELED:
                        // The user was asked to change settings, but chose not to
                        Toast.makeText(HomeActivity.this,"Canceled",Toast.LENGTH_SHORT).show();
                        break;
                    default:
                        break;
                }
                break;
        }
    }

Refer the link SettingsClient

Arul Pandian
  • 1,685
  • 15
  • 20
25

Its Working similar to google maps?
Source Code: https://drive.google.com/open?id=0BzBKpZ4nzNzUOXM2eEhHM3hOZk0

Add Dependency in build.gradle file:

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

OR

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

enter image description here

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;
                    }
                }
            });
        }
    }

}
SMR
  • 6,628
  • 2
  • 35
  • 56
Keshav Gera
  • 10,807
  • 1
  • 75
  • 53
  • 1
    See Broadcast Receiver Post Very Useful and Like me https://stackoverflow.com/questions/15698790/broadcast-receiver-for-checking-internet-connection-in-android-app/44881551#44881551 – Keshav Gera Sep 15 '17 at 07:37
  • 1
    Can you please update the link, it's broken now, post the code in GitHub instead – Manoj Perumarath Jun 23 '20 at 14:07
7

Dependency

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

Code

import android.app.Activity;
import android.content.Context;
import android.content.Intent;
import android.content.IntentSender;
import android.location.LocationManager;
import android.os.Bundle;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.support.v7.app.AppCompatActivity;
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.LocationSettingsStates;
import com.google.android.gms.location.LocationSettingsStatusCodes;

public class MainActivity extends AppCompatActivity implements GoogleApiClient.ConnectionCallbacks, GoogleApiClient.OnConnectionFailedListener {

    public static final int REQUEST_LOCATION=001;

    GoogleApiClient googleApiClient;

    LocationManager locationManager;
    LocationRequest locationRequest;
    LocationSettingsRequest.Builder locationSettingsRequest;
    Context context;


    PendingResult<LocationSettingsResult> pendingResult;


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

        locationManager = (LocationManager) getSystemService(Context.LOCATION_SERVICE);
        if (locationManager.isProviderEnabled(LocationManager.GPS_PROVIDER)) {
            Toast.makeText(this, "Gps is Enabled", Toast.LENGTH_SHORT).show();

        } else {
            mEnableGps();
        }

    }

    public void mEnableGps() {
        googleApiClient = new GoogleApiClient.Builder(context)
                .addApi(LocationServices.API).addConnectionCallbacks(this)
                .addOnConnectionFailedListener(this)
                .build();
        googleApiClient.connect();
        mLocationSetting();
    }

    public void mLocationSetting() {
        locationRequest = LocationRequest.create();
        locationRequest.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY);
        locationRequest.setInterval(1 * 1000);
        locationRequest.setFastestInterval(1 * 1000);

        locationSettingsRequest = new LocationSettingsRequest.Builder().addLocationRequest(locationRequest);

        mResult();

    }

    public void mResult() {
        pendingResult = LocationServices.SettingsApi.checkLocationSettings(googleApiClient, locationSettingsRequest.build());
        pendingResult.setResultCallback(new ResultCallback<LocationSettingsResult>() {
            @Override
            public void onResult(@NonNull LocationSettingsResult locationSettingsResult) {
                Status status = locationSettingsResult.getStatus();


                switch (status.getStatusCode()) {
                    case LocationSettingsStatusCodes.SUCCESS:
                        // All location settings are satisfied. The client can initialize location
                        // requests here.

                        break;
                    case LocationSettingsStatusCodes.RESOLUTION_REQUIRED:

                        try {

                            status.startResolutionForResult(MainActivity.this, REQUEST_LOCATION);
                        } catch (IntentSender.SendIntentException e) {

                        }
                        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;
                }
            }

        });
    }


    //callback method
    @Override
    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
        final LocationSettingsStates states = LocationSettingsStates.fromIntent(data);
        switch (requestCode) {
            case REQUEST_LOCATION:
                switch (resultCode) {
                    case Activity.RESULT_OK:
                        // All required changes were successfully made
                        Toast.makeText(context, "Gps enabled", Toast.LENGTH_SHORT).show();
                        break;
                    case Activity.RESULT_CANCELED:
                        // The user was asked to change settings, but chose not to
                        Toast.makeText(context, "Gps Canceled", Toast.LENGTH_SHORT).show();
                        break;
                    default:
                        break;
                }
                break;
        }
    }


    @Override
    public void onConnected(@Nullable Bundle bundle) {

    }

    @Override
    public void onConnectionSuspended(int i) {

    }

    @Override
    public void onConnectionFailed(@NonNull ConnectionResult connectionResult) {

    }
}
Francis
  • 71
  • 1
  • 2
6

GoogleApiClient is deprecated. New implementation in Kotlin can be as following.

Dependencies

// Google Maps Location Services
implementation 'com.google.android.gms:play-services-location:17.1.0'
implementation 'com.google.android.gms:play-services-maps:17.0.0'

Code

val locationRequest = LocationRequest.create()
    .setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY)
    .setInterval(30 * 1000)
    .setFastestInterval(5 * 1000)

val builder = LocationSettingsRequest.Builder()
    .addLocationRequest(locationRequest)
    .setAlwaysShow(true)

val pendingResult = LocationServices
    .getSettingsClient(activity)
    .checkLocationSettings(builder.build())

pendingResult.addOnCompleteListener { task ->
    if (task.isSuccessful.not()) {
        task.exception?.let {
            if (it is ApiException && it.statusCode == LocationSettingsStatusCodes.RESOLUTION_REQUIRED) {
                // Show the dialog by calling startResolutionForResult(),
                // and check the result in onActivityResult().
                (it as ResolvableApiException).startResolutionForResult(activity,
                    MainActivity.REQUEST_CODE_LOCATION)
            }
        }
    }
}
Ercan
  • 2,601
  • 22
  • 23
4

You can also add several LocationRequests for Builder to achieve "Use GPS, Wi-Fi and mobile networks for location" dialog instead just "Use GPS for location"

LocationSettingsRequest.Builder builder = new LocationSettingsRequest.Builder()
                .addLocationRequest(createLocationRequest(LocationRequest.PRIORITY_BALANCED_POWER_ACCURACY))
                .addLocationRequest(createLocationRequest(LocationRequest.PRIORITY_HIGH_ACCURACY))
                .setAlwaysShow(true);

PendingResult<LocationSettingsResult> result =
                LocationServices.SettingsApi.checkLocationSettings(mGoogleApiClient, builder.build());
Andrey Busik
  • 441
  • 3
  • 16
  • In my case it is enough to use PRIORITY_HIGH_ACCURACY to get sentence "Use GPS, Wi-Fi and mobile networks for location". But it is strange that it works on real device but in simulator does not. In simulator sentence is always without "Use GPS" at the start although I see that simulator device has GPS. – mikep Sep 02 '19 at 06:56
3

In Kotlin, use this code:

import android.app.Activity
import android.content.Intent
import android.content.IntentSender
import android.os.Bundle
import android.util.Log
import androidx.appcompat.app.AppCompatActivity
import com.google.android.gms.common.api.GoogleApiClient
import com.google.android.gms.common.api.PendingResult
import com.google.android.gms.common.api.Status
import com.google.android.gms.location.*

class MainActivity : AppCompatActivity() {
    private var googleApiClient: GoogleApiClient? = null
    private val REQUESTLOCATION = 199
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        enableLoc()
    }
    private fun enableLoc() {
        googleApiClient = GoogleApiClient.Builder(this)
            .addApi(LocationServices.API)
            .addConnectionCallbacks(object : GoogleApiClient.ConnectionCallbacks {
                override fun onConnected(bundle: Bundle?) {}
                override fun onConnectionSuspended(i: Int) {
                    googleApiClient?.connect()
                }
            })
            .addOnConnectionFailedListener {
            }.build()
        googleApiClient?.connect()
        val locationRequest = LocationRequest.create()
        locationRequest.priority = LocationRequest.PRIORITY_HIGH_ACCURACY
        locationRequest.interval = 30 * 1000.toLong()
        locationRequest.fastestInterval = 5 * 1000.toLong()
        val builder = LocationSettingsRequest.Builder()
            .addLocationRequest(locationRequest)
        builder.setAlwaysShow(true)
        val result: PendingResult<LocationSettingsResult> =
            LocationServices.SettingsApi.checkLocationSettings(googleApiClient, builder.build())
        result.setResultCallback { result ->
            val status: Status = result.status
            when (status.statusCode) {
                LocationSettingsStatusCodes.RESOLUTION_REQUIRED -> try {
                    status.startResolutionForResult(
                        this@MainActivity,
                        REQUESTLOCATION
                    )
                } catch (e: IntentSender.SendIntentException) {
                }
            }
        }
    }
    override fun onActivityResult(
        requestCode: Int,
        resultCode: Int,
        data: Intent?
    ) {
        super.onActivityResult(requestCode, resultCode, data)
        when (requestCode) {
            REQUESTLOCATION -> when (resultCode) {
                Activity.RESULT_OK -> Log.d("abc","OK")
                Activity.RESULT_CANCELED -> Log.d("abc","CANCEL")
            }
        }
    }
}
MMG
  • 3,226
  • 5
  • 16
  • 43
3

This is my Kotlin example-

  private fun enableLocation() {
    val locationRequest = LocationRequest.create()
    locationRequest.apply {
        priority =LocationRequest.PRIORITY_HIGH_ACCURACY
        interval = 30 * 1000.toLong()
        fastestInterval = 5 * 1000.toLong()
    }
    val builder = LocationSettingsRequest.Builder()
            .addLocationRequest(locationRequest)
    builder.setAlwaysShow(true)
    val result=
            LocationServices.getSettingsClient(requireContext()).checkLocationSettings(builder.build())
    result.addOnCompleteListener {
        try {
            val response: LocationSettingsResponse = it.getResult(ApiException::class.java)
            println("location>>>>>>> ${response.locationSettingsStates.isGpsPresent}")
            if(response.locationSettingsStates.isGpsPresent)
                //do something
        }catch (e: ApiException){
            when (e.statusCode) {
                LocationSettingsStatusCodes.RESOLUTION_REQUIRED -> try {
                    val intentSenderRequest =
                        IntentSenderRequest.Builder(e.status.resolution).build()
                    launcher.launch(intentSenderRequest)
                } catch (e: IntentSender.SendIntentException) {
                }
            }
        }
    }
}

And use below get Result method

 private var launcher=  registerForActivityResult(ActivityResultContracts.StartIntentSenderForResult()){ result->
  if (result.resultCode == Activity.RESULT_OK) {
      Log.d(TAG, "OK")
      
  } else {
      Log.d(TAG, "CANCEL")
      requireContext().toast("Please Accept Location enable for use this App.")
  }
}
2

Please check my very simple solution to get the user location in the foreground.

  1. GPS Setting dialog
  2. User location with live data.
  3. LocationUtility class is activity life cycle aware to pause/resume the location updates.
  4. Location with the latest FusedLocationProviderClient

https://github.com/Maqsood007/UserLocation-Android/blob/master/app/src/main/java/jetpack/skill/userlocation_android/utils/LocationUtility.kt

enter image description here

enter image description here

Muhammad Maqsood
  • 1,622
  • 19
  • 25
2

New updated answer August 2020 enter link description here

my fragment is like this update if u are using inside your activity

 import android.app.Activity;
import android.content.Intent;
import android.content.IntentSender;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;

import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.fragment.app.Fragment;


import com.google.android.gms.common.api.ApiException;
import com.google.android.gms.common.api.ResolvableApiException;

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.LocationSettingsResponse;

import com.google.android.gms.location.LocationSettingsStatusCodes;
import com.google.android.gms.tasks.OnCompleteListener;
import com.google.android.gms.tasks.Task;

public class FragmentSearch extends Fragment
{

    View SearchFragmentview;
    protected static final int REQUEST_CHECK_SETTINGS = 0x1;


    @Nullable
    @Override
    public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState)
    {
        SearchFragmentview=inflater.inflate(R.layout.fragment_search,container,false);

           getLocationDialog();

        return  SearchFragmentview;

    }

    private void getLocationDialog()
    {
        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); //this is the key ingredient

        Task<LocationSettingsResponse> result =
                LocationServices.getSettingsClient(getContext()).checkLocationSettings(builder.build());



        result.addOnCompleteListener(new OnCompleteListener<LocationSettingsResponse>()
        {
            @Override
            public void onComplete(Task<LocationSettingsResponse> task)
            {
                try {
                    LocationSettingsResponse response = task.getResult(ApiException.class);
                    // All location settings are satisfied. The client can initialize location
                    // requests here.

                }
                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(
                                      getActivity(),
                                        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;
                    }
                }
            }
        });


    }



    public void onActivityResult(int requestCode, int resultCode, Intent data)
    {
        switch (requestCode)
        {
            case REQUEST_CHECK_SETTINGS:
                switch (resultCode)
                {
                    case Activity.RESULT_OK:
                        // All required changes were successfully made

                        break;
                    case Activity.RESULT_CANCELED:
                        // The user was asked to change settings, but chose not to

                        break;
                    default:
                        break;
                }
                break;
        }
    }[enter image description here][2]



}
0

Settings api deprecated use this.

   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;
                }
            }
        });
    }
Kishan Viramgama
  • 893
  • 1
  • 11
  • 23
Yasin Ege
  • 605
  • 4
  • 14
0

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

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



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

        mSettingsClient = LocationServices.getSettingsClient(MainActivity.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(MainActivity.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");
                    }
                });
sarjeet singh
  • 461
  • 4
  • 10