我正在开发一个需要激活GPS的Android应用程序。
我在很多论坛上阅读了很多相关话题,得到的答案是:
不可能
但是... "Cerberus"应用程序可以开启我的GPS... 所以...这是有可能的!
有人能帮助我吗?
不,这是不可能的,也不合适。您不能未经用户授权就管理其手机。用户必须进行交互才能启用GPS。
来自Play商店:
"Cerberus会在您尝试定位设备时自动启用GPS(仅适用于Android < 2.3.3),并且您可以在应用程序配置中保护其免受未经授权的卸载-有关更多信息,请参阅该应用程序的配置"
您可以像这样做:
startActivity(new Intent(android.provider.Settings.ACTION_LOCATION_SOURCE_SETTINGS));
我认为我们有更好的版本可以像谷歌地图那样,在不打开设置的情况下启用位置功能。
它会看起来像这样 -
在gradle中添加依赖 - compile 'com.google.android.gms:play-services-location:10.0.1'
public class MapActivity extends AppCompatActivity {
protected static final String TAG = "LocationOnOff";
private GoogleApiClient googleApiClient;
final static int REQUEST_LOCATION = 199;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
this.setFinishOnTouchOutside(true);
// Todo Location Already on ... start
final LocationManager manager = (LocationManager) MapActivity.this.getSystemService(Context.LOCATION_SERVICE);
if (manager.isProviderEnabled(LocationManager.GPS_PROVIDER) && hasGPSDevice(MapActivity.this)) {
Toast.makeText(MapActivity.this,"Gps already enabled",Toast.LENGTH_SHORT).show();
}
// Todo Location Already on ... end
if(!hasGPSDevice(MapActivity.this)){
Toast.makeText(MapActivity.this,"Gps not Supported",Toast.LENGTH_SHORT).show();
}
if (!manager.isProviderEnabled(LocationManager.GPS_PROVIDER) && hasGPSDevice(MapActivity.this)) {
Log.e("TAG","Gps already enabled");
Toast.makeText(MapActivity.this,"Gps not enabled",Toast.LENGTH_SHORT).show();
enableLoc();
}else{
Log.e("TAG","Gps already enabled");
Toast.makeText(MapActivity.this,"Gps already enabled",Toast.LENGTH_SHORT).show();
}
}
private boolean hasGPSDevice(Context context) {
final LocationManager mgr = (LocationManager) context
.getSystemService(Context.LOCATION_SERVICE);
if (mgr == null)
return false;
final List<String> providers = mgr.getAllProviders();
if (providers == null)
return false;
return providers.contains(LocationManager.GPS_PROVIDER);
}
private void enableLoc() {
if (googleApiClient == null) {
googleApiClient = new GoogleApiClient.Builder(MapActivity.this)
.addApi(LocationServices.API)
.addConnectionCallbacks(new GoogleApiClient.ConnectionCallbacks() {
@Override
public void onConnected(Bundle bundle) {
}
@Override
public void onConnectionSuspended(int i) {
googleApiClient.connect();
}
})
.addOnConnectionFailedListener(new GoogleApiClient.OnConnectionFailedListener() {
@Override
public void onConnectionFailed(ConnectionResult connectionResult) {
Log.d("Location error","Location error " + connectionResult.getErrorCode());
}
}).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);
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();
switch (status.getStatusCode()) {
case LocationSettingsStatusCodes.RESOLUTION_REQUIRED:
try {
// Show the dialog by calling startResolutionForResult(),
// and check the result in onActivityResult().
status.startResolutionForResult(MapActivity.this, REQUEST_LOCATION);
} catch (IntentSender.SendIntentException e) {
// Ignore the error.
}
break;
}
}
});
}
}
之前存在一个漏洞,允许应用程序在没有特殊权限的情况下打开GPS。但是从2.3版本开始(在大多数ROM中),此漏洞已经不存在了。这里有另一篇帖子详细讨论了它:
"GPS已启用"是一个安全设置,因此您必须具有WRITE_SECURE_SETTINGS权限。但是,这是一个受签名保护的权限,因此除非您的应用程序使用制造商的平台证书签名,否则您将无法被授予此权限。
正确的做法是将用户发送到位置设置页面,然后让他们自行决定是否启用GPS,例如:
Intent i = new
Intent(android.provider.Settings.ACTION_LOCATION_SOURCE_SETTINGS);
startActivity(i);
if (!locationManager.isProviderEnabled(LocationManager.GPS_PROVIDER)) {
AlertDialog.Builder builder = new AlertDialog.Builder(this);
builder.setMessage(R.string.gps_disabled_message)
.setCancelable(false)
.setPositiveButton("Yes", new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int id) {
Intent intent = new Intent(Settings.ACTION_LOCATION_SOURCE_SETTINGS);
startActivity(intent);
}
})
.setNegativeButton("No", new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int id) {
dialog.cancel();
}
});
AlertDialog alert = builder.create();
alert.show();
}
这将创建一个警报,并允许用户进入设置屏幕,然后点击返回按钮回到您的应用程序。据我所知,power widget漏洞在2.3以后不再有效。
使用以下代码: //在setContentView(xml)之后调用turnGPSON
private void turnGPSOn() {
String provider = android.provider.Settings.Secure.getString(
getContentResolver(),
android.provider.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);
}
}**
GoogleApiClient已被废弃,我们需要使用SettingsClient和GoogleApi来使GPS无需进入位置设置,就像Google Maps、OLA、Zomato等应用程序一样。下面的代码支持Android 4.4或更低版本至11+的任何版本。
Gradle文件中需要添加以下依赖:
implementation 'com.google.android.gms:play-services-location:17.1.0'
检查GPS状态是开启还是关闭:
private static LocationManager locationManager = (LocationManager) getSystemService(Context.LOCATION_SERVICE);
public static boolean isGpsEnabled(){
return locationManager.isProviderEnabled(LocationManager.GPS_PROVIDER);
}
//Defining constant request code, add in your activity class
private static final int REQUEST_CHECK_SETTINGS = 111;
if(!isGpsEnabled()){
LocationRequest locationRequest = LocationRequest.create();
locationRequest.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY);
LocationSettingsRequest.Builder builder = new LocationSettingsRequest.Builder()
.addLocationRequest(locationRequest);
builder.setAlwaysShow(true); //this displays dialog box like Google Maps with two buttons - OK and NO,THANKS
Task<LocationSettingsResponse> task =
LocationServices.getSettingsClient(this).checkLocationSettings(builder.build());
task.addOnCompleteListener(new OnCompleteListener<LocationSettingsResponse>() {
@Override
public void onComplete(Task<LocationSettingsResponse> task) {
try {
LocationSettingsResponse response = task.getResult(ApiException.class);
// All location settings are satisfied. The client can initialize location
// requests here.
} catch (ApiException exception) {
switch (exception.getStatusCode()) {
case LocationSettingsStatusCodes.RESOLUTION_REQUIRED:
// Location settings are not satisfied. But could be fixed by showing the
// user a dialog.
try {
// Cast to a resolvable exception.
ResolvableApiException resolvable = (ResolvableApiException) exception;
// Show the dialog by calling startResolutionForResult(),
// and check the result in onActivityResult().
resolvable.startResolutionForResult(
YOUR_ACTIVITY.this,
REQUEST_CHECK_SETTINGS);
} catch (IntentSender.SendIntentException e) {
// Ignore the error.
} catch (ClassCastException e) {
// Ignore, should be an impossible 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;
}
}
}
});
} else {
Toast.makeText(getApplicationContext(), "GPS is already Enabled!", Toast.LENGTH_SHORT).show();
}
}
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
final LocationSettingsStates states = LocationSettingsStates.fromIntent(data);
switch (requestCode) {
case REQUEST_CHECK_SETTINGS:
switch (resultCode) {
case Activity.RESULT_OK:
// All required changes were successfully made
Toast.makeText(getApplicationContext(),"User has clicked on OK - So GPS is on", Toast.LENGTH_SHORT).show();
break;
case Activity.RESULT_CANCELED:
// The user was asked to change settings, but chose not to
Toast.makeText(getApplicationContext(),"User has clicked on NO, THANKS - So GPS is still off.", Toast.LENGTH_SHORT).show();
break;
default:
break;
}
break;
}
}
有关官方文档,请参阅 - https://developers.google.com/android/reference/com/google/android/gms/location/SettingsClient
你可能想要查看这个主题
这里是从那个主题复制的代码
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);
}
}
但是这个解决方案并不推荐,因为它可能无法在 Android 版本> 2.3 上使用。请务必查看评论。