Settings.System.getString 和 Settings.Secure.getString 之间的区别



要获取设备 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

最新更新