要获取设备 ID,我通常使用以下代码片段:
String android_id = Settings.System.getString(getContentResolver(), Secure.ANDROID_ID);
今天,当我在Android Studio中查找日志猫时,它说
"....设置android_id已从android.provider.Settings.System移动到android.provider.Settings.Secure,返回只读值。
所以我将我的代码更改为:
String android_id = Settings.Secure.getString(getContentResolver(), Secure.ANDROID_ID);
如您所见,System
刚刚被替换为Secure
,其他任何更改都没有。我想知道他们移动命名空间的区别/原因是什么,隐藏在这种更改的背后。只是出于好奇。
顺便说一句,为了进一步澄清,我的应用程序使用 API16 (4.1.2)
tl;dr answer:本质上,上面的Settings.System.getString正在调用Settings.Secure.getstring。
与往常一样,Android源代码有答案。
以下是 Settings.System (Android 4.1.2) 的 getString 方法:
public synchronized static String getString(ContentResolver resolver, String name) {
if (MOVED_TO_SECURE.contains(name)) {
Log.w(TAG, "Setting " + name + " has moved from android.provider.Settings.System"
+ " to android.provider.Settings.Secure, returning read-only value.");
return Secure.getString(resolver, name);
}
if (sNameValueCache == null) {
sNameValueCache = new NameValueCache(SYS_PROP_SETTING_VERSION, CONTENT_URI,
CALL_METHOD_GET_SYSTEM);
}
return sNameValueCache.getString(resolver, name);
}
以下是Settings.Secure(Android 4.1.2)
public synchronized static String getString(ContentResolver resolver, String name) {
if (sNameValueCache == null) {
sNameValueCache = new NameValueCache(SYS_PROP_SETTING_VERSION, CONTENT_URI,
CALL_METHOD_GET_SECURE);
}
if (sLockSettings == null) {
sLockSettings = ILockSettings.Stub.asInterface(
(IBinder) ServiceManager.getService("lock_settings"));
sIsSystemProcess = Process.myUid() == Process.SYSTEM_UID;
}
if (sLockSettings != null && !sIsSystemProcess
&& MOVED_TO_LOCK_SETTINGS.contains(name)) {
try {
return sLockSettings.getString(name, "0", UserId.getCallingUserId());
} catch (RemoteException re) {
// Fall through
}
}
return sNameValueCache.getString(resolver, name);
}
当您调用Settings.System.getString时,您将看到它检查MOVED_TO_SECURE(哈希表)是否包含该方法调用Secure.getString的名称(ANDROID_ID) 以下是整个MOVED_TO_SECURE哈希表:
private static final HashSet<String> MOVED_TO_SECURE;
static {
MOVED_TO_SECURE = new HashSet<String>(30);
MOVED_TO_SECURE.add(Secure.ANDROID_ID);
MOVED_TO_SECURE.add(Secure.HTTP_PROXY);
MOVED_TO_SECURE.add(Secure.LOCATION_PROVIDERS_ALLOWED);
MOVED_TO_SECURE.add(Secure.LOCK_BIOMETRIC_WEAK_FLAGS);
MOVED_TO_SECURE.add(Secure.LOCK_PATTERN_ENABLED);
MOVED_TO_SECURE.add(Secure.LOCK_PATTERN_VISIBLE);
MOVED_TO_SECURE.add(Secure.LOCK_PATTERN_TACTILE_FEEDBACK_ENABLED);
MOVED_TO_SECURE.add(Secure.LOGGING_ID);
MOVED_TO_SECURE.add(Secure.PARENTAL_CONTROL_ENABLED);
MOVED_TO_SECURE.add(Secure.PARENTAL_CONTROL_LAST_UPDATE);
MOVED_TO_SECURE.add(Secure.PARENTAL_CONTROL_REDIRECT_URL);
MOVED_TO_SECURE.add(Secure.SETTINGS_CLASSNAME);
MOVED_TO_SECURE.add(Secure.USE_GOOGLE_MAIL);
MOVED_TO_SECURE.add(Secure.WIFI_NETWORKS_AVAILABLE_NOTIFICATION_ON);
MOVED_TO_SECURE.add(Secure.WIFI_NETWORKS_AVAILABLE_REPEAT_DELAY);
MOVED_TO_SECURE.add(Secure.WIFI_NUM_OPEN_NETWORKS_KEPT);
MOVED_TO_SECURE.add(Secure.WIFI_ON);
MOVED_TO_SECURE.add(Secure.WIFI_WATCHDOG_ACCEPTABLE_PACKET_LOSS_PERCENTAGE);
MOVED_TO_SECURE.add(Secure.WIFI_WATCHDOG_AP_COUNT);
MOVED_TO_SECURE.add(Secure.WIFI_WATCHDOG_BACKGROUND_CHECK_DELAY_MS);
MOVED_TO_SECURE.add(Secure.WIFI_WATCHDOG_BACKGROUND_CHECK_ENABLED);
MOVED_TO_SECURE.add(Secure.WIFI_WATCHDOG_BACKGROUND_CHECK_TIMEOUT_MS);
MOVED_TO_SECURE.add(Secure.WIFI_WATCHDOG_INITIAL_IGNORED_PING_COUNT);
MOVED_TO_SECURE.add(Secure.WIFI_WATCHDOG_MAX_AP_CHECKS);
MOVED_TO_SECURE.add(Secure.WIFI_WATCHDOG_ON);
MOVED_TO_SECURE.add(Secure.WIFI_WATCHDOG_PING_COUNT);
MOVED_TO_SECURE.add(Secure.WIFI_WATCHDOG_PING_DELAY_MS);
MOVED_TO_SECURE.add(Secure.WIFI_WATCHDOG_PING_TIMEOUT_MS);
// At one time in System, then Global, but now back in Secure
MOVED_TO_SECURE.add(Secure.INSTALL_NON_MARKET_APPS);
}
这样做的原因是,随着谷歌更新Android框架,他们主要出于安全考虑将配置标识符重新组织到不同的位置。通常,发生这种情况是因为Google内部决定应用不应修改某些可用配置。 (除非您可以以某种方式获得WRITE_SECURE_SETTINGS权限,这在典型应用程序中不可用)。而且他们不想破坏旧版本的兼容性,所以他们静默地调用适当的getString,而不是引发异常。
最显着的变化发生在 4.2 之后,他们添加了 Settings.Global 并将大量配置标识符移到了那里。如果需要读取 4.2 之后的设备级别的系统配置,建议改用 Settings.Global 。
源代码:http://grepcode.com/file/repo1.maven.org/maven2/com.google.android/android/4.1.1.4/android/provider/Settings.java