如何在 Android 上以编程方式启用或禁用 GPS?

我知道关于在机器人 已经 曾经 讨论过 很多 时间上程序化打开/关闭 GPS 的问题,答案总是一样的:

“出于安全/隐私方面的原因,你不能这样做,你必须转发到位置首选项屏幕,让用户启用/禁用它。”

我知道,但是我最近从市场上购买了 塔斯克,而且,在你可以用它完成的许多其他事情中,你可以设置规则,在进入预定义的应用程序时自动启用 GPS,并在退出时禁用它(请参阅 给你的教程如何做到这一点,它只是工作这个应用程序不能用固件签名键签名,因为它可以在许多安卓版本和不同的设备上工作,你甚至不需要被植入。

我想在我的应用程序中做到这一点。当然,我不想破坏用户的隐私,所以我首先会问用户是否想使用典型的“记住我的决定”复选框自动打开它,如果他回答是,就启用它。

有人知道塔斯克是怎么做到的吗?

324327 次浏览

也许在 android.server.LocationManagerService课堂上用一些反射技巧。

此外,还有一个方法(从 API 8开始) android.provider.Settings.Secure.setLocationProviderEnabled

GPS 可以被 剥削切换电源管理器小部件中的一个 bug。请参阅这个 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
}

另一个问题给出了一个答案,但它是封闭的,我希望社区也能尝试一下。

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

参见 此评论

此解决方案将需要 WRITE_SETTINGSWRITE_SECURE_SETTINGS权限。

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

这个代码适用于 根深蒂固手机 如果应用程序被移动到 /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

所有这些答案现在都不允许,下面是正确的答案:

对于那些仍在寻找答案的人:

以下是 OLA 出租车和其他类似的应用程序是如何做到这一点的。

在 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 文档

这是为了帮助其他还在苦苦挣扎的人:

编辑 : < em > 添加 Irfan Raza 的评论以获得更多帮助。

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

自从这个问题发布以来,事情已经发生了变化,现在有了新的 Google 服务 API,你可以提示用户启用 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提供的最佳解决方案。只需在初始化 GoogleApiClient之后在 onCreate 的 onResume 中调用此方法。

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没有打开,这行代码会自动打开对话框。< strong > 这一行也在 Google Map 中使用

 status.startResolutionForResult(
MainActivity.this,
PERMISSIONS_REQUEST_ACCESS_FINE_LOCATION);

这段代码适用于有根号码的手机:

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

不需要使用意图设置 ACTION _ LOCATION _ SOURCE _ SETTIES 你可以直接在你的应用中显示出来,比如 Google Map & on Gps,点击 OK 按钮,它们不需要重定向到设置,你只需要使用我的代码作为

注意: 如果 Location 没有打开,这行代码会自动打开对话框。这条线也用在谷歌地图上

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


}
}

注意: 如果 Location 没有打开,这行代码会自动打开对话框。这条线也用在谷歌地图上

你只需要从 LocationManager中移除 LocationListener

manager.removeUpdates(listener);

使用此代码简单易用:

许可:

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

按此密码以编程方式进入全球定位系统:

LocationManager locationManager ;
boolean GpsStatus ;




GPSStatus();


if(GpsStatus == true)
{
textview.setText("Your Location Services Is Enabled");
}else
{textview.setText("Your Location Services Is Disabled");}


Intent intent = new Intent(Settings.ACTION_LOCATION_SOURCE_SETTINGS);
startActivity(intent);




public void GPSStatus(){
locationManager = (LocationManager)context.getSystemService(Context.LOCATION_SERVICE);
GpsStatus = locationManager.isProviderEnabled(LocationManager.GPS_PROVIDER);
}

以上正确答案是非常老的,它需要一些新的东西,所以这里是答案

和上次更新一样,我们支持 androidx,所以首先在应用级 build.gradle 文件中包含依赖关系

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

然后添加清单文件:

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

如果您正在发布,不要忘记获得用户对这些权限的同意

现在这里是代码,只要使用它

 protected void createLocationRequest() {
LocationRequest locationRequest = LocationRequest.create();
locationRequest.setInterval(10000);
locationRequest.setFastestInterval(5000);
locationRequest.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY);


LocationSettingsRequest.Builder builder = new LocationSettingsRequest.Builder()
.addLocationRequest(locationRequest);


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






task.addOnSuccessListener(this, new OnSuccessListener<LocationSettingsResponse>() {
@Override
public void onSuccess(LocationSettingsResponse locationSettingsResponse) {
// All location settings are satisfied. The client can initialize
// location requests here.
// ...


Toast.makeText(MainActivity.this, "Gps already open",
Toast.LENGTH_LONG).show();
Log.d("location settings",locationSettingsResponse.toString());
}
});


task.addOnFailureListener(this, new OnFailureListener() {
@Override
public void onFailure(@NonNull Exception e) {
if (e instanceof ResolvableApiException) {
// 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().
ResolvableApiException resolvable = (ResolvableApiException) e;
resolvable.startResolutionForResult(MainActivity.this,
REQUEST_CHECK_SETTINGS);
} catch (IntentSender.SendIntentException sendEx) {
// Ignore the error.
}
}
}
});
}




@Override
protected void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) {
super.onActivityResult(requestCode, resultCode, data);


if(requestCode==REQUEST_CHECK_SETTINGS){


if(resultCode==RESULT_OK){


Toast.makeText(this, "Gps opened", Toast.LENGTH_SHORT).show();
//if user allows to open gps
Log.d("result ok",data.toString());


}else if(resultCode==RESULT_CANCELED){


Toast.makeText(this, "refused to open gps",
Toast.LENGTH_SHORT).show();
// in case user back press or refuses to open gps
Log.d("result cancelled",data.toString());
}
}
}

如果出了什么问题,请通知我

这个我喜欢。

在这个问题下,这是一个比 Rj0078的回答更简单的解决方案,但是这个方案也起作用了。

它显示了这样一个对话框:

enter image description here

(写于 Kotlin)

    googleApiClient = GoogleApiClient.Builder(context!!)
.addApi(LocationServices.API).build()
googleApiClient!!.connect()
locationRequest = LocationRequest.create()
locationRequest!!.priority = LocationRequest.PRIORITY_HIGH_ACCURACY
locationRequest!!.interval = 30 * 1000.toLong()
locationRequest!!.fastestInterval = 5 * 1000.toLong()


val builder = LocationSettingsRequest.Builder()
.addLocationRequest(locationRequest!!)
builder.setAlwaysShow(true)


result =
LocationServices.SettingsApi.checkLocationSettings(googleApiClient, builder.build())
result!!.setResultCallback { result ->
val status: Status = result.status
when (status.statusCode) {
LocationSettingsStatusCodes.SUCCESS -> {
// Do something
}
LocationSettingsStatusCodes.RESOLUTION_REQUIRED ->
try {
startResolutionForResult(),
status.startResolutionForResult(
activity,
REQUEST_LOCATION
)
} catch (e: SendIntentException) {
}
LocationSettingsStatusCodes.SETTINGS_CHANGE_UNAVAILABLE -> {
// Do something
}
}
}

这对于所有的 Android 版本和可能的新版本来说都是一个更加稳定的代码

void checkGPS() {
LocationRequest locationRequest = LocationRequest.create();


LocationSettingsRequest.Builder builder = new LocationSettingsRequest.Builder().addLocationRequest(locationRequest);


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


task.addOnSuccessListener(this, new OnSuccessListener<LocationSettingsResponse>() {
@Override
public void onSuccess(LocationSettingsResponse locationSettingsResponse) {
Log.d("GPS_main", "OnSuccess");
// GPS is ON
}
});


task.addOnFailureListener(this, new OnFailureListener() {
@Override
public void onFailure(@NonNull final Exception e) {
Log.d("GPS_main", "GPS off");
// GPS off
if (e instanceof ResolvableApiException) {
ResolvableApiException resolvable = (ResolvableApiException) e;
try {
resolvable.startResolutionForResult(ActivityMain.this, REQUESTCODE_TURNON_GPS);
} catch (IntentSender.SendIntentException e1) {
e1.printStackTrace();
}
}
}
});
}

你可以在这里处理 GPS 状态的变化

@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {


if(requestCode == Static_AppVariables.REQUESTCODE_TURNON_GPS) {
switch (resultCode) {
case Activity.RESULT_OK:
// GPS was turned on;
break;
case Activity.RESULT_CANCELED:
// User rejected turning on the GPS
break;
default:
break;
}
}
}

简短,方便的解决方案与最新的 API,从 https://developer.android.com/training/location/change-location-settings.html

你会得到不错的谷歌警报对话框与 ok按钮没有任何需要去设置。

直奔主题,我的碎片代码:

override fun onResume() {
super.onResume()
checkGPSEnabled()
}
private fun checkGPSEnabled() {
val manager = requireContext().getSystemService(Context.LOCATION_SERVICE) as LocationManager
if (manager.isProviderEnabled(LocationManager.GPS_PROVIDER).not()) {
turnOnGPS()
}
}
private fun turnOnGPS() {
val request = LocationRequest.create().apply {
interval = 2000
priority = LocationRequest.PRIORITY_HIGH_ACCURACY
}
val builder = LocationSettingsRequest.Builder().addLocationRequest(request)
val client: SettingsClient = LocationServices.getSettingsClient(requireActivity())
val task: Task<LocationSettingsResponse> = client.checkLocationSettings(builder.build())
task.addOnFailureListener {
if (it is ResolvableApiException) {
try {
it.startResolutionForResult(requireActivity(), 12345)
} catch (sendEx: IntentSender.SendIntentException) {
}
}
}.addOnSuccessListener {
//here GPS is On
}
}

就是这样。只要复制和粘贴。你还需要: implementation 'com.google.android.gms:play-services-location:18.0.0'和舱单 <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"/>