获取位置服务总开关状态
//获取LOCATION_MODE值,但adb状态下无法获取
//0为关闭,1 gps、2 network、3 高精度等
int state = Settings.Secure.getInt(mContext.getContentResolver(),Settings.Secure.LOCATION_MODE,Settings.Secure.LOCATION_MODE_HIGH_ACCURACY);
//获取location_providers_allowed,adb状态下可以读取
String s = Settings.Secure.getString(mContext.getContentResolver(),"location_providers_allowed");
实现
Android5-8
修改Settings.Secure+发送广播
private void setLocationEnabled(Context context, int mode){
int oldMode = Settings.Secure.getInt(context.getContentResolver(),
Settings.Secure.LOCATION_MODE,
Settings.Secure.LOCATION_MODE_OFF);
updateLocationMode(context, oldMode, mode);
}
private boolean updateLocationMode(Context context, int oldMode, int newMode) {
Intent intent = new Intent("com.android.settings.location.MODE_CHANGING");
intent.putExtra("CURRENT_MODE", oldMode);
intent.putExtra("NEW_MODE", newMode);
context.sendBroadcast(intent, android.Manifest.permission.WRITE_SECURE_SETTINGS);
return Settings.Secure.putInt(context.getContentResolver(), Settings.Secure.LOCATION_MODE, newMode);
}
Android9
@RequiresApi(api = Build.VERSION_CODES.P)
public static void setProviderEnabledForUser(Context context, String provider, boolean enabled){
LocationManager locationManager = (LocationManager)context.getSystemService(Context.LOCATION_SERVICE);
try{
Field field = UserHandle.class.getDeclaredField("SYSTEM");
field.setAccessible(true);
UserHandle userHandle = (UserHandle) field.get(UserHandle.class);
Method method = LocationManager.class.getDeclaredMethod(
"setProviderEnabledForUser",
String.class,
boolean.class,
serHandle.class);
method.invoke(locationManager, provider, enabled, userHandle);
}catch(Exception e){
Log.e(TAG, "can not setProviderEnabledForUser:(" + provider +"," + enabled +")");
}
}
Android10以上
@RequiresApi(api = Build.VERSION_CODES.Q)
public static void setLocationEnabledForUser(Context context, boolean enabled){
LocationManager locationManager = (LocationManager)context.getSystemService(Context.LOCATION_SERVICE);
try{
Field field = UserHandle.class.getDeclaredField("SYSTEM");
field.setAccessible(true);
UserHandle userHandle = (UserHandle) field.get(UserHandle.class);
Method method = LocationManager.class.getDeclaredMethod(
"setLocationEnabledForUser",
boolean.class,
UserHandle.class);
method.invoke(locationManager, enabled, userHandle);
}catch(Exception e){
Log.e(TAG, "can not setLocationEnabledForUser:(" + enabled +")");
}
}
实例
关闭位置信息总开关:
public class LocationUtil {
private static void updateLocationMode(Context context, int oldMode, int newMode) {
Intent intent = new Intent("com.android.settings.location.MODE_CHANGING");
intent.putExtra("CURRENT_MODE", oldMode);
intent.putExtra("NEW_MODE", newMode);
context.sendBroadcast(intent, android.Manifest.permission.WRITE_SECURE_SETTINGS);
Settings.Secure.putInt(context.getContentResolver(), Settings.Secure.LOCATION_MODE, newMode);
}
/**
* Settings.Secure.LOCATION_MODE_OFF // 关闭
* Settings.Secure.LOCATION_MODE_SENSORS_ONLY // GPS only
* Settings.Secure.LOCATION_MODE_BATTERY_SAVING // 降低GPS上报频率
* Settings.Secure.LOCATION_MODE_HIGH_ACCURACY // 高精度
*/
public static void setLocationEnabled(Context context, int mode){
int oldMode = Settings.Secure.getInt(context.getContentResolver(),
Settings.Secure.LOCATION_MODE,
Settings.Secure.LOCATION_MODE_OFF);
updateLocationMode(context, oldMode, mode);
}
}
定位默认高精度
Android8.1版本
1.修改xml文件
地址:\SettingsProvider\res\values
<string name="def_location_providers_allowed" translatable="false">gps,network</string>
该种方法只针对于国内应用有效
注:当手动切换到低耗电模式时,重启后会自动开启高精度
当修改含有GMS的海外系统时,单纯修改xml字符串无效,会出现:
1).重启后生效
2).进安卓设置页面后恢复
3).恢复出厂设置后重置
排查原因:
由于是海外系统,有gms
手动点进设置中切换时会有弹窗提示,所以需要在开机之后通过代码进行修改
应用需要满足:
1).系统应用
2).gms开机启动慢,所以选择在接收到开机广播后进行处理,在AndroidMainfest.xml中声明权限
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED"/>
网上查到都是在Launcher的onCreate进行延迟处理,但客户需求不打包UI,而且还要考虑到主题切换等操作,所以在对应的系统应用中添加,用广播处理是一样的。
2.修改java文件
adb获取为null,即用户没有手动更改过定位模式
adb shell settings get system location_mode_changed
注:需要手动切换后再次获取,看看该属性值是否有变化
若无变化,可参考文章:android 默认打开高精度定位模式,accept Improve location accuracy
在Android8.1中,LocationMode.java中有将location_mode_changed属性值进行改变,以达到判断用户手动设置
在开机广播进行处理
// 判断用户是否手动设置了定位模式
int mode = Settings.System.getInt(getContentResolver(), "location_mode_changed", 0);
ContentResolver localContentResolver = getContentResolver();
ContentValues localContentValues = new ContentValues();
localContentValues.put("name", "network_location_opt_in");
localContentValues.put("value", 1);
localContentResolver.insert(Uri.parse("content://com.google.settings/partner"), localContentValues);
if(mode == 0){
Settings.Secure.setLocationProviderEnabled(localContentResolver, "network", true);
}