Domanda Come posso abilitare o disabilitare il GPS a livello di programmazione su Android?


So che la domanda sull'accensione / spegnimento del GPS programmaticamente su Android ha  stato  discusso  molti  voltee la risposta è sempre la stessa:

"Non è possibile per motivi di sicurezza / privacy, è necessario inoltrare alla schermata delle preferenze di posizione e consentire all'utente di abilitarlo / disabilitarlo."

Capisco che, tuttavia, ho comprato di recente Tasker dal mercato e, tra le molte altre cose che è possibile realizzare con esso, è possibile impostare regole per l'auto-abilitazione del GPS all'inserimento di applicazioni predeterminate e disabilitarle all'uscita (vedere Qui per il tutorial su come farlo, e funziona!) e questa app non può essere firmata con la chiave di firma del firmware in quanto funziona su molte versioni di Android e dispositivi diversi e non è nemmeno necessario essere rootati.

Mi piacerebbe farlo nella mia app. Naturalmente, non voglio far esplodere la privacy degli utenti, quindi per prima cosa chiedo all'utente se vuole accenderlo automaticamente con la tipica casella di controllo "ricorda la mia decisione" e se risponde sì, abilitarlo.

Qualcuno ha qualche idea o indizio su come Tasker raggiunge questo?


126
2018-01-18 07:23


origine


risposte:


il GPS può essere attivato da sfruttando un bug nel widget di power manager. guarda questo xda thread per la discussione.

ecco alcuni esempi di codice che uso

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

utilizzare quanto segue per verificare se la versione esistente del widget di controllo dell'alimentazione è quella che consente di attivare il 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
}

150
2018-03-14 23:26



Tutte queste risposte non sono consentite ora. Ecco quello corretto:

Per tutti quelli che stanno ancora cercando la risposta:

Ecco come lo fanno OLA Cabs e altre app di questo tipo.

Aggiungi questo nel tuo 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;
            }
        }
    });
}

Questi sono i metodi impiantati:

@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

}

Ecco il Documentazione Android per lo stesso.

Questo per aiutare gli altri ragazzi se stanno ancora lottando:

modificare: Aggiunta del commento di Irfan Raza per ulteriore aiuto.

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

56
2017-11-05 22:09



ABILITA GPS:

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

DISABILITA GPS:

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

46
2017-07-16 11:14



Questo codice funziona radicato telefoni se l'app è stata spostata  /system/aps, e hanno le seguenti autorizzazioni nel manifest:

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

Codice

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

28
2017-09-22 16:48



Dal momento che Android versione 4.4, non è possibile abilitare / disabilitare gps in modo programmatico. Se provi il codice proposto su questa risposta, verrà emessa un'eccezione.

java.lang.SecurityException: Permission Denial: not allowed to send broadcast android.location.GPS_ENABLED_CHANGE

20
2017-08-04 19:35



Invece di utilizzare l'impostazione Settings.ACTION_LOCATION_SOURCE_SETTINGS puoi visualizzare direttamente popup nella tua app come Google Map e Gps con un clic del pulsante ok non è necessario reindirizzare all'impostazione semplicemente devi usare il mio codice come

Nota: questa riga di codice apre automaticamente la finestra di dialogo se la Posizione non è attiva. Questo pezzo di linea è utilizzato anche in Google Map

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

}

}

Nota: questa riga di codice apre automaticamente la finestra di dialogo se la Posizione non è attiva. Questo pezzo di linea è utilizzato anche in Google Map


13
2018-03-02 13:21



Per attivare o disattivare il GPS programmaticamente è necessario l'accesso "root" e BusyBox installato. Anche con quelli, il compito non è banale.

Il campione è qui: Google Drive, Github, Sourceforge

Testato con Androidi 2.3.5 e 4.1.2.


6
2018-02-13 09:26



Una risposta è stata sviluppata in un'altra domanda, ma è stata chiusa, e mi piacerebbe che anche la comunità provasse.

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

Vedere questo commento

Questa soluzione richiederebbe il WRITE_SETTINGS e WRITE_SECURE_SETTINGS permessi.


2
2018-01-18 14:19



Forse con trucchi di riflessione intorno alla classe android.server.LocationManagerService.

Inoltre, c'è un metodo (dal momento che l'API 8) android.provider.Settings.Secure.setLocationProviderEnabled


2
2018-01-14 21:49



Le cose sono cambiate da quando è stata pubblicata questa domanda, ora con la nuova API di Google Services, puoi chiedere agli utenti di abilitare il GPS:

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

Dovrai richiedere l'autorizzazione ACCESS_FINE_LOCATION nel tuo manifest:

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

Guarda anche questo video:

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


1
2017-12-30 13:19