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

Ge *_*ong 3 java android

要获取设备ID,我通常使用以下代码段:

String android_id = Settings.System.getString(getContentResolver(), Secure.ANDROID_ID);

今天,当我在Android Studio中查找logcat时,它说

"....设置android_id已从android.provider.Settings.System移至android.provider.Settings.Secure,返回只读值."

所以我将我的代码更改为:

String android_id = Settings.Secure.getString(getContentResolver(), Secure.ANDROID_ID);

正如你所看到的,System刚刚被替换Secure,没有别的东西被改变.我想知道他们移动命名空间的区别/原因是什么,这背后是这个变化.只是出于好奇.

顺便说一句,为了进一步澄清,我的应用程序使用API​​16(4.1.2)

l46*_*kok 12

tl;博士回答:实质上,上面的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);
         }
Run Code Online (Sandbox Code Playgroud)

以下是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);
        }
Run Code Online (Sandbox Code Playgroud)

当您调用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);
        }
Run Code Online (Sandbox Code Playgroud)

这样做的原因是,当Google更新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