Elvis Oliveira
Elvis Oliveira

Reputation: 941

How to turn on the GPS on Android

I am developing an android app which needs to activate the GPS.

I read a lot of topics in a lot of forums and the answer I've found is:

it's not possible

But... the "Cerberus" APP turns my GPS on... so... it's possible!

Can anyone help me with this?

Upvotes: 19

Views: 85716

Answers (7)

goodm
goodm

Reputation: 7295

No, it's impossible, and inappropriate. You can't just manage the user's phone without their authority. The user must interact to enable GPS.

From Play Store:

"Cerberus automatically enables GPS if it is off when you try to localize your device (only on Android < 2.3.3) and you can protect it from unauthorized uninstalling - more info in the app configuration."

You can do something like this:

startActivity(new Intent(android.provider.Settings.ACTION_LOCATION_SOURCE_SETTINGS));

Upvotes: 22

Yash Modi
Yash Modi

Reputation: 137

The GoogleApiClient has been deprecated, we need to use SettingsClient and GoogleApi to enable GPS without going to the Location Settings just like Google Maps, OLA, Zomato etc. Below code supports any of the Android Version starting from 4.4 or lower to 11+

dependency required in gradle file:

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

To check GPS state ON or OFF:

private static LocationManager locationManager = (LocationManager) getSystemService(Context.LOCATION_SERVICE);
public static boolean isGpsEnabled(){
        return locationManager.isProviderEnabled(LocationManager.GPS_PROVIDER);
    }

If GPS is already enabled then we will display toast notification otherwise will ask to turn the GPS on.

//Defining constant request code, add in your activity class
private static final int REQUEST_CHECK_SETTINGS = 111;

if(!isGpsEnabled()){
            LocationRequest locationRequest = LocationRequest.create();
            locationRequest.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY);
            LocationSettingsRequest.Builder builder = new LocationSettingsRequest.Builder()
                    .addLocationRequest(locationRequest);

        builder.setAlwaysShow(true); //this displays dialog box like Google Maps with two buttons - OK and NO,THANKS

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

        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(
                                        YOUR_ACTIVITY.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;
                    }
                }
            }
        });
    } else {
        Toast.makeText(getApplicationContext(), "GPS is already Enabled!", Toast.LENGTH_SHORT).show();
    }
}

If GPS is not ON, then flow will come to RESOLUTION_REQUIRED and that will call startResolutionForResult which will be handled by onActivityResult

Now, add onActivityResult method -

@Override
    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
        super.onActivityResult(requestCode, resultCode, data);
        final LocationSettingsStates states = LocationSettingsStates.fromIntent(data);

        switch (requestCode) {
            case REQUEST_CHECK_SETTINGS:
                switch (resultCode) {
                    case Activity.RESULT_OK:
                        // All required changes were successfully made
                        Toast.makeText(getApplicationContext(),"User has clicked on OK - So GPS is on", Toast.LENGTH_SHORT).show();
                        break;
                    case Activity.RESULT_CANCELED:
                        // The user was asked to change settings, but chose not to
                        Toast.makeText(getApplicationContext(),"User has clicked on NO, THANKS - So GPS is still off.", Toast.LENGTH_SHORT).show();
                        break;
                    default:
                        break;
                }
                break;
        }
    }

If resultCode is RESULT_OK that means user allowed to turn GPS on else for RESULT_CANCELED, you can again ask or show the rationale dialog.

  • You can wrap above code in method and call wherever you require
  • While building LocationRequest you can set Interval, Priority, SmallestDisplacement, FastestInterval, etc as per you required by your app.
  • We have used Task api instead of PendingResult

For Official Document, refer - https://developers.google.com/android/reference/com/google/android/gms/location/SettingsClient

Upvotes: 2

A J
A J

Reputation: 4632

I think we have more better version to enable the location without opening the settings just like google map works.

It will looks like this -

enter image description here

Add Dependency in gradle - compile 'com.google.android.gms:play-services-location:10.0.1'

public class MapActivity 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) MapActivity.this.getSystemService(Context.LOCATION_SERVICE);
        if (manager.isProviderEnabled(LocationManager.GPS_PROVIDER) && hasGPSDevice(MapActivity.this)) {
            Toast.makeText(MapActivity.this,"Gps already enabled",Toast.LENGTH_SHORT).show();
        }
        // Todo Location Already on  ... end

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

        if (!manager.isProviderEnabled(LocationManager.GPS_PROVIDER) && hasGPSDevice(MapActivity.this)) {
            Log.e("TAG","Gps already enabled");
            Toast.makeText(MapActivity.this,"Gps not enabled",Toast.LENGTH_SHORT).show();
            enableLoc();
        }else{
            Log.e("TAG","Gps already enabled");
            Toast.makeText(MapActivity.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(MapActivity.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(MapActivity.this, REQUEST_LOCATION);
                       } catch (IntentSender.SendIntentException e) {
                           // Ignore the error.
                       }
                       break;
                 }
             }
         });
     }

}

Upvotes: 16

Jeffrey Blattman
Jeffrey Blattman

Reputation: 22637

There used to be an exploit that allowed the GPS to be turned on by an app with no special permissions. That exploit no longer exists as of 2.3 (in most ROMs). Here's another post that talks about it,

How can I enable or disable the GPS programmatically on Android?

"GPS enabled" is a secure setting, so you must have WRITE_SECURE_SETTINGS permission. This is a signature protected permission however, so you app will not be granted this unless it is signed with the manufacturer's platform certificate.

The correct thing is to send the user to the location settings page, and let them enable GPS if they wish. e.g.,

Intent i = new
Intent(android.provider.Settings.ACTION_LOCATION_SOURCE_SETTINGS);
startActivity(i);

Upvotes: 13

Sanket
Sanket

Reputation: 499

Use this code //turnGPSON called After setcontentView(xml)

 private void turnGPSOn() {

    String provider = android.provider.Settings.Secure.getString(
            getContentResolver(),
            android.provider.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);
    }
}**

Upvotes: 2

Kevin
Kevin

Reputation: 532

    if (!locationManager.isProviderEnabled(LocationManager.GPS_PROVIDER)) {
        AlertDialog.Builder builder = new AlertDialog.Builder(this);
        builder.setMessage(R.string.gps_disabled_message)
        .setCancelable(false)
        .setPositiveButton("Yes", new DialogInterface.OnClickListener() {
            public void onClick(DialogInterface dialog, int id) {
                    Intent intent = new Intent(Settings.ACTION_LOCATION_SOURCE_SETTINGS);
                    startActivity(intent);                  
            }
        })
        .setNegativeButton("No", new DialogInterface.OnClickListener() {
            public void onClick(DialogInterface dialog, int id) {
                dialog.cancel();
            }
        });
        AlertDialog alert = builder.create();
        alert.show();
    }

This creates an alert and allows the user to go to the settings screen and hit the back button to come right back to your app. The power widget exploit doesn't work beyond 2.3 to my knowledge.

Upvotes: 5

Rejinderi
Rejinderi

Reputation: 11844

you might want to check out this thread

How can I enable or disable the GPS programmatically on Android?

here are the codes copied from that thread

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


   }
}

but the solution is not recommended as it will not be available to android version > 2.3 supposingly.. do check the comments

Upvotes: 1

Related Questions