SettingsProvider之System内部类

本文介绍Android系统中设置项从Settings.System迁移到Settings.Secure和Settings.Global的过程,并提供了字段转移、字符串获取与设置等方法的具体实现。

转载请注明出处:http://blog.youkuaiyun.com/droyon/article/details/35558995

1、字段转移
MOVED_TO_SECURE = new HashSet<String>(30);
            MOVED_TO_SECURE.add(Secure.ANDROID_ID);
            MOVED_TO_SECURE.add(Secure.HTTP_PROXY);

MOVED_TO_GLOBAL = new HashSet<String>();
            MOVED_TO_SECURE_THEN_GLOBAL = new HashSet<String>();

            // these were originally in system but migrated to secure in the past,
            // so are duplicated in the Secure.* namespace
            MOVED_TO_SECURE_THEN_GLOBAL.add(Global.ADB_ENABLED);
            MOVED_TO_SECURE_THEN_GLOBAL.add(Global.BLUETOOTH_ON);

MOVED_TO_GLOBAL.add(Settings.Global.AIRPLANE_MODE_ON);
            MOVED_TO_GLOBAL.add(Settings.Global.AIRPLANE_MODE_RADIOS);
            MOVED_TO_GLOBAL.add(Settings.Global.AIRPLANE_MODE_TOGGLEABLE_RADIOS);


/** @hide */
        public static void getMovedKeys(HashSet<String> outKeySet) {
            outKeySet.addAll(MOVED_TO_GLOBAL);
            outKeySet.addAll(MOVED_TO_SECURE_THEN_GLOBAL);
        }

        /** @hide */
        public static void getNonLegacyMovedKeys(HashSet<String> outKeySet) {
            outKeySet.addAll(MOVED_TO_GLOBAL);
        }

2、构建sNameValueCache。
private static final NameValueCache sNameValueCache = new NameValueCache(
                SYS_PROP_SETTING_VERSION,
                CONTENT_URI,
                CALL_METHOD_GET_SYSTEM,
                CALL_METHOD_PUT_SYSTEM);


3、获取String
/** @hide */
        public static String getStringForUser(ContentResolver resolver, String name,
                int userHandle) {
            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.getStringForUser(resolver, name, userHandle);
            }
            if (MOVED_TO_GLOBAL.contains(name) || MOVED_TO_SECURE_THEN_GLOBAL.contains(name)) {
                Log.w(TAG, "Setting " + name + " has moved from android.provider.Settings.System"
                        + " to android.provider.Settings.Global, returning read-only value.");
                return Global.getStringForUser(resolver, name, userHandle);
            }
            return sNameValueCache.getStringForUser(resolver, name, userHandle);
        }

4、putString
/** @hide */
        public static boolean putStringForUser(ContentResolver resolver, String name, String value,
                int userHandle) {
            if (MOVED_TO_SECURE.contains(name)) {
                Log.w(TAG, "Setting " + name + " has moved from android.provider.Settings.System"
                        + " to android.provider.Settings.Secure, value is unchanged.");
                return false;
            }
            if (MOVED_TO_GLOBAL.contains(name) || MOVED_TO_SECURE_THEN_GLOBAL.contains(name)) {
                Log.w(TAG, "Setting " + name + " has moved from android.provider.Settings.System"
                        + " to android.provider.Settings.Global, value is unchanged.");
                return false;
            }
            return sNameValueCache.putStringForUser(resolver, name, value, userHandle);
        }

5、getUriFor
public static Uri getUriFor(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 Secure URI.");
                return Secure.getUriFor(Secure.CONTENT_URI, name);
            }
            if (MOVED_TO_GLOBAL.contains(name) || MOVED_TO_SECURE_THEN_GLOBAL.contains(name)) {
                Log.w(TAG, "Setting " + name + " has moved from android.provider.Settings.System"
                        + " to android.provider.Settings.Global, returning read-only global URI.");
                return Global.getUriFor(Global.CONTENT_URI, name);
            }
            return getUriFor(CONTENT_URI, name);
        }

<think>我们正在讨论Android中的Settings Provider。根据用户要求,需要详细解释其工作原理、作用以及开发指南。 参考站内引用,我们注意到引用[1]提到了ContentProvider的一些基本属性,如authorities、权限等,这与Settings Provider密切相关,因为Settings Provider本身就是一种ContentProvider。 另外,引用[2]和[3]似乎与当前问题关联不大,但我们可以专注于引用[1]中关于ContentProvider的说明。 首先,我们需要明确:AndroidSettings Provider是一个系统级的ContentProvider,用于管理设备上的全局设置信息(包括系统设置和用户设置)。它提供了访问和修改这些设置的接口。 以下将分三个部分进行详细说明: 1. 作用: - 存储系统设置(如飞行模式开关、屏幕亮度、音量等)和用户设置(如自定义系统配置)。 - 提供统一的访问接口,供应用程序读取和修改设置(但需要适当的权限)。 - 维护设置的持久化存储(通常存储在数据库中)。 2. 工作原理: - Settings Provider继承自ContentProvider,因此它通过URI来标识数据,并通过ContentResolver进行访问。 - 系统设置分为多种类型,分别存储在不同的表中。例如: * 全局设置(Global):所有用户共享的设置,通常需要特殊权限才能修改。 * 系统设置(System):针对每个用户的系统设置。 * 安全设置(Secure):安全相关的设置,修改需要更高的权限。 - 访问这些设置的URI通常为: * `content://settings/global` * `content://settings/system` * `content://settings/secure` - 当应用程序通过ContentResolver请求访问设置时,Settings Provider会根据URI确定要访问的表,然后执行相应的查询或更新操作。 3. 开发指南: - 读取设置:使用`Settings.System.getInt()`, `Settings.Global.getString()`等静态方法(内部通过ContentResolver实现)。 - 修改设置:使用`Settings.System.putInt()`, `Settings.Global.putString()`等方法(需要声明并获取相应的权限)。 - 权限:修改系统设置通常需要`WRITE_SETTINGS`权限(在Android 6.0及以上,该权限属于危险权限,需要动态申请)。对于安全设置,可能需要系统签名权限。 - 自定义设置:应用程序可以添加自己的设置项,但建议使用自己的ContentProvider,而不是直接添加到系统设置中(避免冲突)。 注意:直接修改系统设置可能会影响设备稳定性,因此应谨慎使用,并确保用户知情。 下面是一个简单的示例代码,展示如何读取和修改系统设置(此处以系统亮度为例): ```java // 读取当前系统亮度 try { int brightness = Settings.System.getInt(getContentResolver(), Settings.System.SCREEN_BRIGHTNESS); Log.d("Settings", "Current brightness: " + brightness); } catch (Settings.SettingNotFoundException e) { e.printStackTrace(); } // 修改系统亮度(需要WRITE_SETTINGS权限) if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) { if (Settings.System.canWrite(this)) { Settings.System.putInt(getContentResolver(), Settings.System.SCREEN_BRIGHTNESS, 200); } else { // 请求WRITE_SETTINGS权限 Intent intent = new Intent(Settings.ACTION_MANAGE_WRITE_SETTINGS); intent.setData(Uri.parse("package:" + getPackageName())); startActivity(intent); } } ``` 最后,需要提醒的是,从Android 8.0(API 26)开始,部分设置项可能被限制访问,因此开发时需注意目标API级别。 根据以上内容,生成相关问题: 1. 如何动态申请WRITE_SETTINGS权限? 2. 系统设置、全局设置和安全设置有什么区别? 3. 如何为应用程序创建自定义设置项? 4.Android高版本中,访问系统设置有哪些限制?</think>### Android Settings Provider 详解 #### 一、作用 Settings ProviderAndroid 系统的核心组件,负责管理系统配置数据的存储和访问,主要作用包括: 1. **统一配置管理**:集中存储系统级和用户级设置(如飞行模式开关、屏幕亮度、WiFi状态等) 2. **数据持久化**:将设置数据持久存储在 SQLite 数据库中(位于 `/data/data/com.android.providers.settings/databases/settings.db`) 3. **权限控制**:通过 Android 权限机制控制对敏感设置的访问[^1] 4. **配置同步**:支持跨设备同步设置(通过 BackupManager) 5. **多用户支持**:为不同用户账户维护独立的配置空间 #### 二、工作原理 1. **数据分层结构**: - `Global`:所有用户共享的全局设置(如设备名称) - `System`:用户级系统设置(如屏幕超时) - `Secure`:安全敏感设置(如位置服务开关) ```mermaid graph TD A[SettingsProvider] --> B[Global 表] A --> C[System 表] A --> D[Secure 表] ``` 2. **访问流程**: ```java // 读取设置示例 int brightness = Settings.System.getInt( getContentResolver(), Settings.System.SCREEN_BRIGHTNESS ); // 写入设置示例(需权限) Settings.System.putInt( getContentResolver(), Settings.System.SCREEN_BRIGHTNESS, 200 ); ``` 1. 应用通过 `ContentResolver` 发送请求 2. 系统根据 URI 路由到 SettingsProvider ```uri content://settings/system content://settings/global content://settings/secure ``` 3. Provider 执行数据库操作 4. 广播设置变更(如 `ACTION_AIRPLANE_MODE_CHANGED`) 3. **数据存储**: | 表名 | 字段 | 示例值 | |------------|------------------|-----------------------| | global | name | airplane_mode_on | | global | value | 1 | | system | name | screen_brightness | | system | value | 120 | #### 三、开发指南 1. **访问设置**: ```java // 读取设置 String deviceName = Settings.Global.getString( contentResolver, Settings.Global.DEVICE_NAME ); // 写入设置(需要 WRITE_SETTINGS 权限) if (Settings.System.canWrite(context)) { Settings.System.putInt( contentResolver, Settings.System.SCREEN_OFF_TIMEOUT, 300000 // 5分钟 ); } ``` 2. **权限声明**: ```xml <!-- AndroidManifest.xml --> <uses-permission android:name="android.permission.WRITE_SETTINGS"/> <uses-permission android:name="android.permission.READ_SETTINGS"/> ``` 3. **自定义设置**(系统应用): ```java // 定义新设置项 public static final String MY_CUSTOM_SETTING = "custom_setting"; // 注册到系统 Settings.System.putString( contentResolver, MY_CUSTOM_SETTING, "default_value" ); ``` 4. **监听设置变更**: ```java ContentObserver observer = new ContentObserver(new Handler()) { @Override public void onChange(boolean selfChange) { // 处理设置变更 } }; contentResolver.registerContentObserver( Settings.System.CONTENT_URI, true, observer ); ``` #### 四、注意事项 1. **权限限制**: - 普通应用只能访问非敏感设置 - 修改 `Secure` 表需要系统签名权限 2. **线程安全**:所有操作自动同步,避免手动加锁 3. **性能优化**:批量操作使用 `ContentProviderOperation` 4. **版本兼容**:不同 Android 版本设置项可能变化 5. **车载系统注意**:定制 ROM 可能修改默认行为[^2] > 关键参考:Settings Provider 通过 `android:authorities="settings"` 声明其内容提供者标识[^1],其核心实现类为 `SettingsProvider.java`(AOSP 路径:`frameworks/base/packages/SettingsProvider/src/`)
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

hailushijie

您的鼓励是我创作最大的动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值