173

I know that the question about turning on/off GPS programatically on android has been discussed many times, and the answer is always the same:

"You can't for security/privacy reasons, you have to forward to location preferences screen and let the user enable/disable it."

I understand that, however I recently bought Tasker from the market and, among many other things that you can accomplish with it, you can set rules to auto-enable GPS on entering pre-determined applications and disable it on exit (see here for the tutorial on how to do it, and it just works!) and this app can't be signed with the firmware signing key as it works on many android versions and different devices and you don't even need to be rooted.

I would like to do this in my app. Of course, I don't want to blow up the users privacy, so I would first ask the user if he wants to turn it on automatically with the typical "remember my decision" checkbox and if he answers yes, enable it.

Does anybody have any idea or clue on how Tasker achieves this?

Community
  • 1
  • 1
maid450
  • 7,478
  • 3
  • 37
  • 32
  • I want to turn GPS off and on so I can write tests on code that demands it's on. Without mocks, because Android makes those a pain – Phlip Feb 22 '21 at 23:02

17 Answers17

160

the GPS can be toggled by exploiting a bug in the power manager widget. see this xda thread for discussion.

here's some example code i use

private void turnGPSOn(){
    String provider = Settings.Secure.getString(getContentResolver(), Settings.Secure.LOCATION_PROVIDERS_ALLOWED);

    if(!provider.contains("gps")){ //if gps is disabled
        final Intent poke = new Intent();
        poke.setClassName("com.android.settings", "com.android.settings.widget.SettingsAppWidgetProvider"); 
        poke.addCategory(Intent.CATEGORY_ALTERNATIVE);
        poke.setData(Uri.parse("3")); 
        sendBroadcast(poke);
    }
}

private void turnGPSOff(){
    String provider = Settings.Secure.getString(getContentResolver(), Settings.Secure.LOCATION_PROVIDERS_ALLOWED);

    if(provider.contains("gps")){ //if gps is enabled
        final Intent poke = new Intent();
        poke.setClassName("com.android.settings", "com.android.settings.widget.SettingsAppWidgetProvider");
        poke.addCategory(Intent.CATEGORY_ALTERNATIVE);
        poke.setData(Uri.parse("3")); 
        sendBroadcast(poke);
    }
}

use the following to test if the existing version of the power control widget is one which will allow you to toggle the gps.

private boolean canToggleGPS() {
    PackageManager pacman = getPackageManager();
    PackageInfo pacInfo = null;

    try {
        pacInfo = pacman.getPackageInfo("com.android.settings", PackageManager.GET_RECEIVERS);
    } catch (NameNotFoundException e) {
        return false; //package not found
    }

    if(pacInfo != null){
        for(ActivityInfo actInfo : pacInfo.receivers){
            //test if recevier is exported. if so, we can toggle GPS.
            if(actInfo.name.equals("com.android.settings.widget.SettingsAppWidgetProvider") && actInfo.exported){
                return true;
            }
        }
    }

    return false; //default
}
Ben H
  • 3,855
  • 1
  • 26
  • 33
  • hmmm interesting... I was sure it would not be a very "legal" way to do this... thanks! – maid450 Mar 15 '11 at 10:06
  • 4
    At the time of this (my) comment, the links in this answer seem to indicate that the bug this exploits has recently been fixed. I just wanted to point out that the exploit still seems to work just fine in my own test environment, so you shouldn't give up on trying this... just be sure that your code will handle any errors if it doesn't work! – SilithCrowe Jun 22 '11 at 16:47
  • 1
    As of this comment's writing, this exploit **still works** on a 2.2.1 Android phone. Nice find, Ben H. – Qix - MONICA WAS MISTREATED Aug 17 '11 at 15:33
  • yes, the bug was supposedly fixed in android 2.3. however, some custom 2.3+ ROMs include the unfixed version of the power control widget, so it works on them. – Ben H Aug 22 '11 at 21:53
  • Hello , here com.android.settings is app Package name or what ? – Girish Patel Nov 14 '11 at 11:19
  • yes, that is the package that contains the power control widget. – Ben H Dec 13 '11 at 20:19
  • Anyone know the status of this with honeycomb and ICS? – Patrick Jackson May 04 '12 at 02:58
  • It turns on GPS as displayed in Settings, but when I try to get a location from GPS provider, it doesn't give me any new locations. – amit May 10 '12 at 23:15
  • any solution to ON GPS for versions above: 2.2 – Aakash May 11 '12 at 11:51
  • Is there ay way to tirn on aGPS... Is the way similar! Ben thanks, it really works! – timonvlad Jun 28 '12 at 11:24
  • aGPS can't be turned on or off. it's dependent on GPS, so if GPS is off, then aGPS isn't available either. are you perhaps asking about cell tower location instead? that should be active by default as long as the phone isn't in airplane mode. – Ben H Jun 29 '12 at 16:48
  • what if i have root permission for my app? is it possible to use it in order to toggle gps on/off without using the exploit , even on newer android versions? – android developer Jul 21 '12 at 23:39
  • i don't believe so. if your app is installed as a system app (in /system/app), then you can use the WRITE_SECURE_SETTINGS permission and the Settings.Secure class to toggle the GPS. root alone is not going to give you WRITE_SECURE_SETTINGS. this is just a guess, but you might be able to edit the settings database (settings.db) using sqlite and root. – Ben H Jul 23 '12 at 03:40
  • 52
    This is a really bad idea. Once the bug gets fixed, your exploit will no longer work. Better to just send the user to the settings app. – Edward Falk Nov 15 '12 at 22:30
  • 1
    Working fine in Android 2.3.6 but not working android 4.0.3 . Any idea to enable or disable in android 4.0.3 – Krishna Jan 02 '13 at 12:44
  • 5
    hahaha... this exploit reemerged in 4.2.2, Surprised to see it.. GOD! – amithgc Apr 16 '13 at 11:57
  • 1
    It's not a feasible solution any more. Seems android has fixed that issue, so it looks like working in bar but it's hardware is still OFF and won't through any locations except value 0.0 in both lat & lon. – Harpreet Aug 23 '13 at 06:39
  • 1
    `Settings.Secure.LOCATION_PROVIDERS_ALLOWED` is deprecated on `KITKAT`. This is the time when this trick doesn't work any more. – Shnkc Apr 08 '15 at 11:00
  • its not working , when this code executed for disabling gps BUT when i check manually i see gps is enable not disable. Please help me to resolve this.Thanks in advance! – Gyan Swaroop Awasthi Apr 27 '20 at 14:39
77

All these answers are not allowed now. Here is the correct one:

For all those still looking for the Answer:

Here is how OLA Cabs and other such apps are doing it.

Add this in your onCreate

if (googleApiClient == null) {
    googleApiClient = new GoogleApiClient.Builder(this)
            .addApi(LocationServices.API).addConnectionCallbacks(this)
            .addOnConnectionFailedListener(Login.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(Login.this, 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;
            }
        }
    });
}

These are the implmented methods:

@Override
public void onConnected(Bundle arg0) {
    // TODO Auto-generated method stub

}

@Override
public void onConnectionSuspended(int arg0) {
    // TODO Auto-generated method stub

}

@Override
public void onConnectionFailed(ConnectionResult arg0) {
    // TODO Auto-generated method stub

}

Here is the Android Documentation for the same.

This is to help other guys if they are still struggling:

Edit: Adding Irfan Raza's comment for more help.

@Override protected void onActivityResult(int requestCode, int resultCode, Intent data) {
     if (requestCode == 1000) {
         if(resultCode == Activity.RESULT_OK){
             String result=data.getStringExtra("result"); 
         } if (resultCode == Activity.RESULT_CANCELED) {
             //Write your code if there's no result 
         } 
    } 
} 
Aishvarya Jaiswal
  • 1,793
  • 6
  • 34
  • 72
  • Now this answer should be the accepted one. Thanks a lot Akshat!! – Gurpreet Mar 04 '16 at 04:58
  • 2
    Needs Google API client integration hence only a solution for specific use cases, not fit for a generic solution. – Cik Apr 23 '16 at 12:40
  • @DilroopSingh what problem are you facing.? I am using the same code and it works perfectly. – Aishvarya Jaiswal Jul 07 '16 at 07:38
  • 1
    can we achieve this without showing that builder.Because i need to turn on gps without showing any alerts. – Punithapriya Jul 26 '16 at 06:57
  • 3
    @Punithapriya Thats not possible. User consent is must and thus that builder has to be shown. – Aishvarya Jaiswal Jul 26 '16 at 11:45
  • Yes, i know that but i wanted to track the user without knowing him. – Punithapriya Jul 26 '16 at 12:02
  • Thanks @Akshat. Its working at my end. But onConnected method always fires even before the popup appears. So basically irrespective of whether user allows Ok or cancel the consent, onConnected gets called with bundle as null. Is there any way that I can get to know when user has clicked the OK button?, so I can do further processing. – Irfan Raza Dec 04 '16 at 19:49
  • I figured it out. It was very simple. This is to help other guys if they are still struggling: @Override protected void onActivityResult(int requestCode, int resultCode, Intent data) { if (requestCode == 1000) { if(resultCode == Activity.RESULT_OK){ String result=data.getStringExtra("result"); } if (resultCode == Activity.RESULT_CANCELED) { //Write your code if there's no result } } } – Irfan Raza Dec 04 '16 at 20:13
  • Where do i have to put this code? I had put it in onStart()..but not receiving any update in on location changed Listener. – Umesh Chauhan Dec 16 '16 at 17:55
  • This answer is also deprecated now. Check here : https://developers.google.com/android/reference/com/google/android/gms/location/SettingsClient – Vaibhav Jani Feb 19 '18 at 07:57
  • does this method still work ? I need a valid response. – Naveen Niraula Jul 23 '18 at 10:06
  • How to stop location update once we get it so that power consumption can be reduced – Ankit Mishra Jun 08 '20 at 12:08
50

ENABLE GPS:

Intent intent=new Intent("android.location.GPS_ENABLED_CHANGE");
intent.putExtra("enabled", true);
sendBroadcast(intent);

DISABLE GPS:

Intent intent = new Intent("android.location.GPS_ENABLED_CHANGE");
intent.putExtra("enabled", false);
sendBroadcast(intent);
mob_web_dev
  • 2,342
  • 1
  • 20
  • 42
  • 1
    automatically GPS will turn on/off. – mob_web_dev Jul 16 '12 at 11:19
  • 1
    This also helps to enable. private void turnGPSOn(){ String provider = Settings.Secure.getString(getContentResolver(), Settings.Secure.LOCATION_PROVIDERS_ALLOWED); if(!provider.contains("gps")){ //if gps is disabled final Intent poke = new Intent(); poke.setClassName("com.android.settings", "com.android.settings.widget.SettingsAppWidgetProvider"); poke.addCategory(Intent.CATEGORY_ALTERNATIVE); poke.setData(Uri.parse("3")); sendBroadcast(poke); } } – mob_web_dev Jul 26 '12 at 11:27
  • in android 2.3.4 running on asamsung sII it turns the gps icon on without effectively activating the gps sensor. But, if you choose to turn the GPS sensor on programmatically, it is then recognized. – tony gil Aug 06 '12 at 00:38
  • 25
    android 4.0.4 - only gps **notification** is enabled. not the gps itself. so it looks like it's on but in fact it's not – alex Aug 21 '12 at 07:20
  • @alex: For security reasons I hope the opposite is not possible. Namely to query location (GPS or A-GPS) but suppress the UI notification for it. Or is it possible? – porg Oct 02 '13 at 21:30
  • 17
    java.lang.SecurityException: Permission Denial: not allowed to send broadcast android.location.GPS_ENABLED_CHANGE – Abhi Apr 15 '16 at 13:57
  • It not work and show this error: java.lang.SecurityException: Permission Denial: not allowed to send broadcast android.location.GPS_ENABLED_CHANGE – K.Sopheak Apr 06 '17 at 08:38
28

This code works on ROOTED phones if the app is moved to /system/aps, and they have the following permissions in the manifest:

<uses-permission android:name="android.permission.WRITE_SETTINGS"/>
<uses-permission android:name="android.permission.WRITE_SECURE_SETTINGS"/>

Code

private void turnGpsOn (Context context) {
    beforeEnable = Settings.Secure.getString (context.getContentResolver(),
                                              Settings.Secure.LOCATION_PROVIDERS_ALLOWED);
    String newSet = String.format ("%s,%s",
                                   beforeEnable,
                                   LocationManager.GPS_PROVIDER);
    try {
        Settings.Secure.putString (context.getContentResolver(),
                                   Settings.Secure.LOCATION_PROVIDERS_ALLOWED,
                                   newSet); 
    } catch(Exception e) {}
}


private void turnGpsOff (Context context) {
    if (null == beforeEnable) {
        String str = Settings.Secure.getString (context.getContentResolver(),
                                                Settings.Secure.LOCATION_PROVIDERS_ALLOWED);
        if (null == str) {
            str = "";
        } else {                
            String[] list = str.split (",");
            str = "";
            int j = 0;
            for (int i = 0; i < list.length; i++) {
                if (!list[i].equals (LocationManager.GPS_PROVIDER)) {
                    if (j > 0) {
                        str += ",";
                    }
                    str += list[i];
                    j++;
                }
            }
            beforeEnable = str;
        }
    }
    try {
        Settings.Secure.putString (context.getContentResolver(),
                                   Settings.Secure.LOCATION_PROVIDERS_ALLOWED,
                                   beforeEnable);
    } catch(Exception e) {}
}
Nate Zaugg
  • 4,202
  • 2
  • 36
  • 53
26

Instead of using intent Settings.ACTION_LOCATION_SOURCE_SETTINGS you can directly able to show pop up in your app like Google Map & on Gps on click of ok button their is no need to redirect to setting simply you need to use my code as

Note : This line of code automatic open the dialog box if Location is not on. This piece of line is used in Google Map also

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


LocationRequest mLocationRequest;
GoogleApiClient mGoogleApiClient;
PendingResult<LocationSettingsResult> result;
final static int REQUEST_LOCATION = 199;

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

    mGoogleApiClient = new GoogleApiClient.Builder(this)
            .addApi(LocationServices.API)
            .addConnectionCallbacks(this)
            .addOnConnectionFailedListener(this).build();
    mGoogleApiClient.connect();

}

@Override
public void onConnected(Bundle bundle) {

    mLocationRequest = LocationRequest.create();
    mLocationRequest.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY);
    mLocationRequest.setInterval(30 * 1000);
    mLocationRequest.setFastestInterval(5 * 1000);

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

    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_LOCATION);
                    } catch (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
public void onActivityResult(int requestCode, int resultCode, Intent data)
{
    Log.d("onActivityResult()", Integer.toString(resultCode));

    //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(MainActivity.this, "Location enabled by user!", Toast.LENGTH_LONG).show();
                    break;
                }
                case Activity.RESULT_CANCELED:
                {
                    // The user was asked to change settings, but chose not to
                    Toast.makeText(MainActivity.this, "Location not enabled, user cancelled.", Toast.LENGTH_LONG).show();
                    break;
                }
                default:
                {
                    break;
                }
            }
            break;
    }
}

@Override
public void onConnectionSuspended(int i) {

}

@Override
public void onConnectionFailed(ConnectionResult connectionResult) {

}
} 

Note : This line of code automatic open the dialog box if Location is not on. This piece of line is used in Google Map also

Thecave3
  • 762
  • 12
  • 27
The Black Horse
  • 2,328
  • 1
  • 14
  • 21
23

Since Android version 4.4, you can't enable/disable gps programatically. If you try the code proposed on this answer, an exception will be fired.

java.lang.SecurityException: Permission Denial: not allowed to send broadcast android.location.GPS_ENABLED_CHANGE
Community
  • 1
  • 1
Amaury Medeiros
  • 2,093
  • 4
  • 26
  • 42
11

Above correct answer is very old it needs something new so Here is answer

As in last update we have androidx support so first include dependency in your app level build.gradle file

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

then add in your manifest file:

<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION"/>
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"/>

don't forget to take user consent for these permissions if you are releasing

now here is code just use it

 protected void createLocationRequest() {
    LocationRequest locationRequest = LocationRequest.create();
    locationRequest.setInterval(10000);
    locationRequest.setFastestInterval(5000);
    locationRequest.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY);

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

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



    task.addOnSuccessListener(this, new OnSuccessListener<LocationSettingsResponse>() {
        @Override
        public void onSuccess(LocationSettingsResponse locationSettingsResponse) {
            // All location settings are satisfied. The client can initialize
            // location requests here.
            // ...

            Toast.makeText(MainActivity.this, "Gps already open", 
                                          Toast.LENGTH_LONG).show();
            Log.d("location settings",locationSettingsResponse.toString());
        }
    });

    task.addOnFailureListener(this, new OnFailureListener() {
        @Override
        public void onFailure(@NonNull Exception e) {
            if (e instanceof 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().
                    ResolvableApiException resolvable = (ResolvableApiException) e;
                    resolvable.startResolutionForResult(MainActivity.this,
                            REQUEST_CHECK_SETTINGS);
                } catch (IntentSender.SendIntentException sendEx) {
                    // Ignore the error.
                }
            }
        }
    });
}


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

    if(requestCode==REQUEST_CHECK_SETTINGS){

        if(resultCode==RESULT_OK){

            Toast.makeText(this, "Gps opened", Toast.LENGTH_SHORT).show();
            //if user allows to open gps
            Log.d("result ok",data.toString());

        }else if(resultCode==RESULT_CANCELED){

            Toast.makeText(this, "refused to open gps", 
                                         Toast.LENGTH_SHORT).show();
            // in case user back press or refuses to open gps
            Log.d("result cancelled",data.toString());
        }
    }
}

if something goes wrong please ping me

7

Short and easy solution with newest API, from https://developer.android.com/training/location/change-location-settings.html.

You will get nice Google AlertDialog with ok button without any need of going to settings.

Straight to the point. My code in Fragment:

override fun onResume() {
        super.onResume()
        checkGPSEnabled()
    }
private fun checkGPSEnabled() {
        val manager = requireContext().getSystemService(Context.LOCATION_SERVICE) as LocationManager
        if (manager.isProviderEnabled(LocationManager.GPS_PROVIDER).not()) {
            turnOnGPS()
        }
    }
private fun turnOnGPS() {
        val request = LocationRequest.create().apply {
            interval = 2000
            priority = LocationRequest.PRIORITY_HIGH_ACCURACY
        }
        val builder = LocationSettingsRequest.Builder().addLocationRequest(request)
        val client: SettingsClient = LocationServices.getSettingsClient(requireActivity())
        val task: Task<LocationSettingsResponse> = client.checkLocationSettings(builder.build())
        task.addOnFailureListener {
            if (it is ResolvableApiException) {
                try {
                    it.startResolutionForResult(requireActivity(), 12345)
                } catch (sendEx: IntentSender.SendIntentException) {
                }
            }
        }.addOnSuccessListener {
            //here GPS is On
        }
    }

That's it. Just copy and paste. You will need also: implementation 'com.google.android.gms:play-services-location:18.0.0' and in Manifest <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"/>

Peter Z.
  • 159
  • 1
  • 5
3

This code works on ROOTED phones:

public class MainActivity extends AppCompatActivity {

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

        String[] cmds = {"cd /system/bin" ,"settings put secure location_providers_allowed +gps"};
        try {
            Process p = Runtime.getRuntime().exec("su");
            DataOutputStream os = new DataOutputStream(p.getOutputStream());
            for (String tmpCmd : cmds) {
                os.writeBytes(tmpCmd + "\n");
            }
            os.writeBytes("exit\n");
            os.flush();
        }
        catch (IOException e){
            e.printStackTrace();
        }
    }
}

For turning off GPS you can use this command instead

settings put secure location_providers_allowed -gps

You can also toggle network accuracy using the following commands: for turning on use:

settings put secure location_providers_allowed +network

and for turning off you can use:

settings put secure location_providers_allowed -network
Steve Moretz
  • 2,758
  • 1
  • 17
  • 31
DarwinFernandez
  • 344
  • 2
  • 6
2

An answer was developed in another question, but it was closed, and I'd like the community to try it out as well.

boolean gpsStatus = locmanager.isProviderEnabled(LocationManager.GPS_PROVIDER);
if (!gpsStatus) {
    Settings.Secure.putString(getContentResolver(), Settings.Secure.LOCATION_PROVIDERS_ALLOWED, "network,gps");
}

See this comment

This solution would require the WRITE_SETTINGS and WRITE_SECURE_SETTINGS permissions.

Community
  • 1
  • 1
gobernador
  • 5,659
  • 3
  • 32
  • 51
  • @milind , suppose i have a rooted device , what should i do in order to use this code? i've tried to get a root permission for the app , but it didn't help . it keeps saying "Permission denial: writing to secure settings requires android.permission.WRITE_SECURE_SETTINGS" – android developer Aug 04 '12 at 10:23
  • @android Read the last sentence of this post. Using this method will require the `android.permission.WRITE_SECURE_SETTINGS` permission in the Manifest. – gobernador Aug 04 '12 at 15:18
  • 1
    i know . i've already added it . it tells me that even though it's already in the manifest. – android developer Aug 04 '12 at 17:00
  • @android [It looks like you're not the first one to have this problem](http://stackoverflow.com/questions/4721449/enable-gps-programatically-like-tasker/10004614#comment5223375_4725106) – gobernador Aug 05 '12 at 03:36
  • so it's impossible even for rooted devices?! – android developer Aug 05 '12 at 05:55
  • @androiddeveloper you can convert your application into System app and try this..this snippet will work! – Ayush Goyal Apr 04 '13 at 18:22
2

This is the best solution provided by Google Developers. Simply call this method in onResume of onCreate after initializing GoogleApiClient.

private void updateMarkers() {
    if (mMap == null) {
        return;
    }

    if (mLocationPermissionGranted) {
        // Get the businesses and other points of interest located
        // nearest to the device's current location.
         mGoogleApiClient = new GoogleApiClient.Builder(this)
                .addApi(LocationServices.API).build();
        mGoogleApiClient.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);


        LocationSettingsRequest.Builder builder = new LocationSettingsRequest
                .Builder()
                .addLocationRequest(mLocationRequest);
        PendingResult<LocationSettingsResult> resultPendingResult = LocationServices
                .SettingsApi
                .checkLocationSettings(mGoogleApiClient, builder.build());

        resultPendingResult.setResultCallback(new ResultCallback<LocationSettingsResult>() {
            @Override
            public void onResult(@NonNull LocationSettingsResult locationSettingsResult) {
                final Status status = locationSettingsResult.getStatus();
                final LocationSettingsStates locationSettingsStates = locationSettingsResult.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 this can 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,
                                    PERMISSIONS_REQUEST_ACCESS_FINE_LOCATION);
                        } 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;
                }

            }
        });


        @SuppressWarnings("MissingPermission")
        PendingResult<PlaceLikelihoodBuffer> result = Places.PlaceDetectionApi
                .getCurrentPlace(mGoogleApiClient, null);
        result.setResultCallback(new ResultCallback<PlaceLikelihoodBuffer>() {
            @Override
            public void onResult(@NonNull PlaceLikelihoodBuffer likelyPlaces) {
                for (PlaceLikelihood placeLikelihood : likelyPlaces) {
                    // Add a marker for each place near the device's current location, with an
                    // info window showing place information.
                    String attributions = (String) placeLikelihood.getPlace().getAttributions();
                    String snippet = (String) placeLikelihood.getPlace().getAddress();
                    if (attributions != null) {
                        snippet = snippet + "\n" + attributions;
                    }

                    mMap.addMarker(new MarkerOptions()
                            .position(placeLikelihood.getPlace().getLatLng())
                            .title((String) placeLikelihood.getPlace().getName())
                            .snippet(snippet));
                }
                // Release the place likelihood buffer.
                likelyPlaces.release();
            }
        });
    } else {
        mMap.addMarker(new MarkerOptions()
                .position(mDefaultLocation)
                .title(getString(R.string.default_info_title))
                .snippet(getString(R.string.default_info_snippet)));
    }
}

Note : This line of code automatic open the dialog box if Location is not on. This piece of line is used in Google Map also

 status.startResolutionForResult(
 MainActivity.this,
 PERMISSIONS_REQUEST_ACCESS_FINE_LOCATION);
AMAN SINGH
  • 3,491
  • 6
  • 28
  • 44
2

Maybe with reflection tricks around the class android.server.LocationManagerService.

Also, there is a method (since API 8) android.provider.Settings.Secure.setLocationProviderEnabled

Gilles 'SO- stop being evil'
  • 104,111
  • 38
  • 209
  • 254
Damian Kołakowski
  • 2,731
  • 22
  • 25
  • 3
    This `Settings.Secure` class seems promising, however I get a security exception saying that I need android.permission.WRITE_SECURE_SETTINGS, and I keep getting the error even adding this permission (and WRITE_SETTINGS also) to my manifest. But it seems a good way to keep searching. Thanks :) – maid450 Jan 18 '11 at 18:52
  • `WRITE_SECURE_SETTINGS` has a **[protection level of `systemOrSignature`](http://developer.android.com/guide/topics/manifest/permission-element.html#plevel)** you need to make that app a system app for it to work, [which is also mentioned in this answer](http://stackoverflow.com/a/18946258/194894). – Flow Feb 06 '14 at 11:19
2

This one works for me.

It is a simpler solution than Rj0078's answer under this question, but that one is worked as well.

It shows a dialog like this:

enter image description here

(Written in Kotlin)

    googleApiClient = GoogleApiClient.Builder(context!!)
        .addApi(LocationServices.API).build()
    googleApiClient!!.connect()
    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)

    result =
       LocationServices.SettingsApi.checkLocationSettings(googleApiClient, builder.build())
    result!!.setResultCallback { result ->
        val status: Status = result.status
        when (status.statusCode) {
            LocationSettingsStatusCodes.SUCCESS -> {
               // Do something
            }
            LocationSettingsStatusCodes.RESOLUTION_REQUIRED ->
                try {
                    startResolutionForResult(),
                    status.startResolutionForResult(
                        activity,
                        REQUEST_LOCATION
                    )
                } catch (e: SendIntentException) {
                }
            LocationSettingsStatusCodes.SETTINGS_CHANGE_UNAVAILABLE -> {
                // Do something
            }
        }
    }
Marci
  • 899
  • 10
  • 13
1

Things have changed since this question was posted, now with new Google Services API, you can prompt users to enable GPS:

https://developers.google.com/places/android-api/current-place

You will need to request ACCESS_FINE_LOCATION permission in your manifest:

<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />

Also watch this video:

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

Human
  • 8,380
  • 2
  • 19
  • 15
1

This is a more statble code for all Android versions and possibly for new ones

void checkGPS() {
    LocationRequest locationRequest = LocationRequest.create();

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

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

    task.addOnSuccessListener(this, new OnSuccessListener<LocationSettingsResponse>() {
        @Override
        public void onSuccess(LocationSettingsResponse locationSettingsResponse) {
            Log.d("GPS_main", "OnSuccess");
            // GPS is ON
        }
    });

    task.addOnFailureListener(this, new OnFailureListener() {
        @Override
        public void onFailure(@NonNull final Exception e) {
            Log.d("GPS_main", "GPS off");
            // GPS off
            if (e instanceof ResolvableApiException) {
                ResolvableApiException resolvable = (ResolvableApiException) e;
                try {
                    resolvable.startResolutionForResult(ActivityMain.this, REQUESTCODE_TURNON_GPS);
                } catch (IntentSender.SendIntentException e1) {
                    e1.printStackTrace();
                }
            }
        }
    });
}

And you can handle the GPS state changes here

@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {

    if(requestCode == Static_AppVariables.REQUESTCODE_TURNON_GPS) {
        switch (resultCode) {
            case Activity.RESULT_OK:
                // GPS was turned on;
                break;
            case Activity.RESULT_CANCELED:
                // User rejected turning on the GPS
                break;
            default:
                break;
        }
    }
}
0

You just need to remove the LocationListener from LocationManager

manager.removeUpdates(listener);
leonardkraemer
  • 6,573
  • 1
  • 31
  • 54
sass
  • 73
  • 1
  • 2
  • 8
0

Use This code Simple and Easy to Access:

Permissions:

<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"/>
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>

Follow this Code to access the GPS programmatically:

LocationManager locationManager ;
 boolean GpsStatus ;


            GPSStatus();

            if(GpsStatus == true)
            {
                textview.setText("Your Location Services Is Enabled");
            }else
                {textview.setText("Your Location Services Is Disabled");}

            Intent intent = new Intent(Settings.ACTION_LOCATION_SOURCE_SETTINGS);
            startActivity(intent);


    public void GPSStatus(){
    locationManager = (LocationManager)context.getSystemService(Context.LOCATION_SERVICE);
    GpsStatus = locationManager.isProviderEnabled(LocationManager.GPS_PROVIDER);
} 
Gaurav Lambole
  • 273
  • 3
  • 3