Как я могу включить или отключить GPS программно на Android?
Я знаю, что вопрос о включении / выключении GPS программно на android ибылообсуждалимноговремени, и ответ всегда один:
" вы не можете по соображениям безопасности/конфиденциальности, вы должны перенаправить на экран настроек местоположения и позволить пользователю включить/отключить его."
Я понимаю, что, однако, я недавно купил Tasker от рынок и, среди многих других вещей, которые вы можете сделать с ним, вы можете установить правила для автоматического включения GPS при входе в заранее определенные приложения и отключить его на выходе (см. здесь для учебника о том, как это сделать, и это просто работает!) и это приложение не может быть подписано с помощью ключа подписи прошивки, поскольку оно работает на многих версиях android и разных устройствах, и вам даже не нужно укореняться.
Я хотел бы сделать это в мое приложение. Конечно, я не хочу взрываться конфиденциальность пользователей, поэтому я бы сначала спросил пользователя, хочет ли он включить его автоматически с помощью типичного флажка "запомнить мое решение", и если он ответит "да", включите его.
есть ли у кого-нибудь идеи или подсказки о том, как Tasker достигает этого?
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" />
также смотрите это видео:
Это лучшее решение, предоставленное
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);