Android Location开关过程分析
有同事发现目前车机的location位置在刷机(线刷之后),每次的location初始值(在settings中看见的)都不一致.之前对这个是一点都没接触过,所以今天拿出来研究下,凑一篇博客.
location的三种工作模式?
从settings->location界面来看,location主要有三种工作模式:
high_accuracy battery_saving sensors_only
对应代码:
//packages/apps/Settings/src/com/android/settings/location/LocationMode.java
int mode = Settings.Secure.LOCATION_MODE_OFF;//其实还有一种off模式
if (emiter == mHighAccuracy) {
mode = Settings.Secure.LOCATION_MODE_HIGH_ACCURACY;
} else if (emiter == mBatterySaving) {
mode = Settings.Secure.LOCATION_MODE_BATTERY_SAVING;
} else if (emiter == mSensorsOnly) {
mode = Settings.Secure.LOCATION_MODE_SENSORS_ONLY;
}
setLocationMode(mode);
迅速找到setLocationMode
//packages/apps/Settings/src/com/android/settings/location/LocationSettingsBase.java
public void setLocationMode(int mode) {
if (isRestricted()) {
// Location toggling disabled by user restriction. Read the current location mode to
// update the location master switch.
if (Log.isLoggable(TAG, Log.INFO)) {
Log.i(TAG, "Restricted user, not setting location mode");
}
mode = Settings.Secure.getInt(getContentResolver(), Settings.Secure.LOCATION_MODE,
Settings.Secure.LOCATION_MODE_OFF);
if (mActive) {
onModeChanged(mode, true);
}
return;
}
Intent intent = new Intent(MODE_CHANGING_ACTION);
intent.putExtra(CURRENT_MODE_KEY, mCurrentMode);
intent.putExtra(NEW_MODE_KEY, mode);
getActivity().sendBroadcast(intent, android.Manifest.permission.WRITE_SECURE_SETTINGS);
Settings.Secure.putInt(getContentResolver(), Settings.Secure.LOCATION_MODE, mode);
refreshLocationMode();
}
看上去就是操作Settings.Secure数据库嘛.直接去找到吧:
private static final boolean setLocationModeForUser(ContentResolver cr, int mode,
int userId) {
...
switch (mode) {
case LOCATION_MODE_OFF:
break;
case LOCATION_MODE_SENSORS_ONLY:
gps = true;
break;
case LOCATION_MODE_BATTERY_SAVING:
network = true;
break;
case LOCATION_MODE_HIGH_ACCURACY:
gps = true;
network = true;
break;
default:
throw new IllegalArgumentException("Invalid location mode: " + mode);
}
// Note it's important that we set the NLP mode first. The Google implementation
// of NLP clears its NLP consent setting any time it receives a
// LocationManager.PROVIDERS_CHANGED_ACTION broadcast and NLP is disabled. Also,
// it shows an NLP consent dialog any time it receives the broadcast, NLP is
// enabled, and the NLP consent is not set. If 1) we were to enable GPS first,
// 2) a setup wizard has its own NLP consent UI that sets the NLP consent setting,
// and 3) the receiver happened to complete before we enabled NLP, then the Google
// NLP would detect the attempt to enable NLP and show a redundant NLP consent
// dialog. Then the people who wrote the setup wizard would be sad.
boolean nlpSuccess = Settings.Secure.setLocationProviderEnabledForUser(
cr, LocationManager.NETWORK_PROVIDER, network, userId);
boolean gpsSuccess = Settings.Secure.setLocationProviderEnabledForUser(
cr, LocationManager.GPS_PROVIDER, gps, userId);
return gpsSuccess && nlpSuccess;
}
public static final boolean setLocationProviderEnabledForUser(ContentResolver cr,
String provider, boolean enabled, int userId) {
synchronized (mLocationSettingsLock) {
// to ensure thread safety, we write the provider name with a '+' or '-'
// and let the SettingsProvider handle it rather than reading and modifying
// the list of enabled providers.
if (enabled) {
provider = "+" + provider;
} else {
provider = "-" + provider;
}
return putStringForUser(cr, Settings.Secure.LOCATION_PROVIDERS_ALLOWED, provider,
userId);
}
}
是的,字段就是它了:Settings.Secure.LOCATION_PROVIDERS_ALLOWED
再看看实际机器测试:
老规矩,一条命令搞定
adb shell settings get secure location_providers_allowed
1.关闭location:
结果空
2.开location,high_accuracy模式
network,gps
3.开location,battery_saving模式
network
4.开location,sensors_only模式
gps
就这样.也算科普学习了!