java - Settings.System.getString 和 Settings.Secure.getString 的区别?

标签 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,没有其他任何变化。我想知道他们移动命名空间的区别/原因是什么,这就是这一变化背后的原因。只是出于好奇。

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

最佳答案

tl;dr 回答:本质上,上面的 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(哈希表)是否包含名称 (ANDROID_ID),该方法改为调用 Secure.getString 这是整个 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 内部决定应用不应修改某些可用配置。 (Unless if you can somehow acquire 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

关于java - Settings.System.getString 和 Settings.Secure.getString 的区别?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/28978550/

相关文章:

android - itext for android 和 lint 错误

java - 如何关闭已建立的网络连接?

android - AWS S3 Java SDK : detect time/clock skew programmatically?

java - 更改 JButton 焦点区域

java - 来自 Java 的 Apple 扁平封装 (pkg)

java - 在javafx gridpane中添加不可见行

java - Maven 使用旧版本的 pom.xml

java - 如何将数组列表接受到方法中

安卓市场文本格式

android - 从 ArrayList<Object> 创建 Spinner