Как я могу включить или отключить GPS программно на Android? - PullRequest
145 голосов
/ 18 января 2011

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

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

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

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

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

Ответы [ 14 ]

160 голосов
/ 15 марта 2011

GPS можно переключать с помощью , используя ошибку в виджете менеджера питания.см. этот xda 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);
    }
}

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

Все эти ответы сейчас не разрешены. Вот правильный:

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

Вот как это делают 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 для того же.

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

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

@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 
         } 
    } 
} 
49 голосов
/ 16 июля 2012

ВКЛЮЧИТЬ 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);
28 голосов
/ 22 сентября 2013

Этот код работает на 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) {}
}
22 голосов
/ 04 августа 2014

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

java.lang.SecurityException: Permission Denial: not allowed to send broadcast android.location.GPS_ENABLED_CHANGE
20 голосов
/ 02 марта 2017

Вместо того, чтобы использовать намерение Settings.ACTION_LOCATION_SOURCE_SETTINGS, вы можете напрямую отображать всплывающие окна в своем приложении, такие как Google Map и Gps, при нажатии кнопки ОК их не нужно перенаправлять на настройки, просто вам нужно использовать мой код как

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

6 голосов
/ 13 февраля 2013

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

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

Протестированос Android 2.3.5 и 4.1.2.

2 голосов
/ 30 декабря 2016

Этот код работает на телефонах с ROOTED:

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
2 голосов
/ 29 ноября 2016

Это лучшее решение, предоставленное 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);
2 голосов
/ 04 апреля 2012

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

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.

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