Как я могу включить или отключить GPS программно на Android?


Я знаю, что вопрос о включении / выключении GPS программно на android ибылообсуждалимноговремени, и ответ всегда один:

" вы не можете по соображениям безопасности/конфиденциальности, вы должны перенаправить на экран настроек местоположения и позволить пользователю включить/отключить его."

Я понимаю, что, однако, я недавно купил Tasker от рынок и, среди многих других вещей, которые вы можете сделать с ним, вы можете установить правила для автоматического включения GPS при входе в заранее определенные приложения и отключить его на выходе (см. здесь для учебника о том, как это сделать, и это просто работает!) и это приложение не может быть подписано с помощью ключа подписи прошивки, поскольку оно работает на многих версиях android и разных устройствах, и вам даже не нужно укореняться.

Я хотел бы сделать это в мое приложение. Конечно, я не хочу взрываться конфиденциальность пользователей, поэтому я бы сначала спросил пользователя, хочет ли он включить его автоматически с помощью типичного флажка "запомнить мое решение", и если он ответит "да", включите его.

есть ли у кого-нибудь идеи или подсказки о том, как Tasker достигает этого?

13 130

13 ответов:

GPS можно переключать с помощью эксплуатации ошибка в виджете power manager. смотрите это XDA нить для обсуждения.

вот пример кода, который я использую

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

используйте следующее, чтобы проверить, является ли существующая версия виджета управления питанием той, которая позволит вам переключать 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
}

все эти ответы теперь не допускаются. Вот правильный:

для всех тех, кто все еще ищет ответ:

вот как OLA Cabs и другие подобные приложения делают это.

добавьте это в свой 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;
            }
        }
    });
}

это имплицированные методы:

@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

}

здесь Документация Для Android то же самое.

Это, чтобы помочь другим ребятам, если они все еще борются:

Edit:добавление комментария Ирфана раза для получения дополнительной помощи.

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

ВКЛЮЧИТЬ GPS:

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

ОТКЛЮЧИТЬ GPS:

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

этот код работает на ROOTED телефоны если приложение перемещается в/system/aps,и они имеют следующие разрешения в манифесте:

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

код

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

начиная с версии Android 4.4, вы не можете включить / отключить gps программно. Если вы попробуете код, предложенный на ответ исключение будет уволен.

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

вместо использования настроек намерения.ACTION_LOCATION_SOURCE_SETTINGS вы можете напрямую показать всплывающее окно в своем приложении, например, Google Map & on Gps при нажатии кнопки ok их не нужно перенаправлять на настройку просто вам нужно использовать мой код как

Примечание: эта строка кода автоматически открывает диалоговое окно, если Location не включен. Этот кусок используется в 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) {

}

}

Примечание: эта строка кода автоматически открывает диалоговое окно, если расположение не включено. Этот кусок используется в Google Map также

для включения или выключения GPS программно вам нужен "корневой" доступ и BusyBox установлен. Даже с теми, задача не тривиальная.

пример здесь: Google Drive,Github,Sourceforge

испытанный с андроидами 2.3.5 и 4.1.2.

ответ был разработан в другом вопросе, но он был закрыт, и я хотел бы, чтобы сообщество также попробовало его.

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

посмотреть комментарий

Это решение потребует WRITE_SETTINGS и WRITE_SECURE_SETTINGS разрешения.

может быть, с отражением трюков вокруг класса android.server.LocationManagerService.

кроме того, есть метод (начиная с API 8) android.provider.Settings.Secure.setLocationProviderEnabled

этот код работает на корневых телефонах:

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

для отключения GPS вы можете использовать эту команду вместо

settings put secure location_providers_allowed -gps

вы также можете переключать точность сети с помощью следующих команд: для включения используйте:

settings put secure location_providers_allowed +network

и для выключения вы можете использовать:

settings put secure location_providers_allowed -network

все изменилось с тех пор, как этот вопрос был опубликован, теперь с новым API сервисов Google вы можете предложить пользователям включить GPS:

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

вам нужно будет запросить разрешение ACCESS_FINE_LOCATION в манифесте:

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

также смотрите это видео:

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

Это лучшее решение, предоставленное Google Developers. Просто вызовите этот метод в onResume onCreate после инициализации 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)));
    }
}

Примечание : эта строка кода автоматически открывает диалоговое окно, если Location не на. этот кусок линии используется в Google Map также

 status.startResolutionForResult(
 MainActivity.this,
 PERMISSIONS_REQUEST_ACCESS_FINE_LOCATION);

вам просто нужно удалить LocationListener С LocationManager

manager.removeUpdates(listener);