SettingsProvider升级流程

SettingsProvider 升级流程

一、修改配置文件

​ 文件:SettingsProvider/res/values/defaults.xml

<string name="def_private_dns_mode" translatable="false">off</string>

二、修改版本号及升级:

​ 修改文件:SettingsProvider/src/com/android/providers/settings/SettingsProvider.java

//版本号修改:
//static final int SETTINGS_VERSION = 182;
static final int SETTINGS_VERSION = 183;
//升级
if (currentVersion == 182) {
    final SettingsState globalSettings = getGlobalSettingsLocked();
    globalSettings.insertSettingLocked(Global.PRIVATE_DNS_MODE,
    getContext().getResources().getString(R.string.def_private_dns_mode), null,true, SettingsState.SYSTEM_PACKAGE_NAME);
    currentVersion = 183;
}

备注:如果是新增的字段需要在Settings.Global中增加对应的KEY

<think>我们正在处理一个Android开发中与设置存储相关的警告问题。警告信息是:"SettingsProvider warning: You shouldn't keep your settings in the secure settings. This will soon become an error"。这意味着在未来的版本中,当前的做法将会导致错误。 根据引用[1]和[2]的内容,这个异常是在Android M(6.0)及更高版本中,当应用尝试使用`Settings.System`存储本属于安全设置(secure settings)的数据时抛出的。在Android中,设置分为三种类型:`System`、`Secure`和`Global`。其中: - `System`:用于存储应用程序的偏好设置,这些设置不会同步,且在恢复出厂设置时会被清除。 - `Secure`:用于存储设备的安全相关设置,这些设置只有系统应用或具有特定权限的应用才能修改。 - `Global`:用于存储全局设置(通常与硬件相关)。 警告信息表明,开发者试图将应该存储在系统设置(System)中的数据存储到了安全设置(Secure)中,而这是不被允许的。在未来的版本中,这种行为将会被阻止并抛出错误。 ### 解决方案 1. **检查设置存储位置**:确认你的设置数据是否确实需要存储在安全设置中。通常,只有涉及设备安全性的设置(如默认锁屏、默认输入法等)才应该存储在安全设置中。应用级别的设置应该使用`Settings.System`或应用自己的SharedPreferences。 2. **迁移到正确的存储位置**: - 如果是应用级别的设置,应该使用`SharedPreferences`来存储。 - 如果是系统级别的设置(需要跨应用共享),并且不需要安全级别的保护,则使用`Settings.System`。 - 如果设置确实是安全相关的,并且你的应用拥有相应的权限(如系统应用或拥有签名权限),则可以继续使用`Settings.Secure`,但需要确保你的应用有资格这样做。 3. **修改代码**: - 将原本使用`Settings.Secure`存储的应用设置改为使用`SharedPreferences`或`Settings.System`(如果设置需要系统级共享)。 例如,原本使用`Settings.Secure`的代码: ```java // 不安全的做法(将普通设置存储在安全设置中) Settings.Secure.putInt(getContentResolver(), "my_setting", 1); ``` 应改为使用`SharedPreferences`(推荐用于应用私有设置): ```java SharedPreferences prefs = getSharedPreferences("my_prefs", Context.MODE_PRIVATE); SharedPreferences.Editor editor = prefs.edit(); editor.putInt("my_setting", 1); editor.apply(); ``` 或者,如果设置需要被其他应用读取(系统级设置),则使用`Settings.System`(注意:需要声明`WRITE_SETTINGS`权限): ```java // 在AndroidManifest.xml中添加权限 // <uses-permission android:name="android.permission.WRITE_SETTINGS"/> // 注意:在Android 6.0及以上,WRITE_SETTINGS权限属于危险权限,需要动态申请 if (Settings.System.canWrite(context)) { Settings.System.putInt(getContentResolver(), "my_setting", 1); } else { // 请求用户授权 Intent intent = new Intent(Settings.ACTION_MANAGE_WRITE_SETTINGS); intent.setData(Uri.parse("package:" + context.getPackageName())); startActivity(intent); } ``` 4. **处理兼容性**: - 如果你的应用需要兼容旧版本(Android M之前),则需要在运行时判断系统版本,在旧版本上使用`Settings.Secure`,而在新版本上使用正确的存储方式(但这种情况很少见,因为通常应用设置不应该存储在系统设置中,更不应该在安全设置中)。 ### 注意事项 - 在Android中,`Settings.System`和`Settings.Secure`的数据库是分开的。系统设置表是`system`,安全设置表是`secure`。 - 从Android M开始,Google加强了设置存储的管理,不允许将普通设置放入安全设置中,因为安全设置需要更高的权限才能修改。 - 使用`SharedPreferences`是最简单且推荐的方式存储应用私有设置,除非设置需要被其他应用访问(这时才考虑使用`Settings.System`,并注意权限问题)。 ### 引用说明 根据引用[1]和[2],这个异常是由于在Android M及更高版本中,将普通设置存储到安全设置中导致的。因此,我们需要将设置迁移到正确的位置[^1][^2]。 §§相关问题§§ 1. Android中系统设置(System)和安全设置(Secure)有什么区别? 2. 如何正确使用SharedPreferences存储应用设置? 3. Android中WRITE_SETTINGS权限的申请流程是怎样的? 4. 如何为不同Android版本实现设置存储的兼容性?</think>### Android SettingsProvider 警告 "You shouldn't keep your settings in the secure settings" 解决方案 #### 问题分析 该警告发生在Android 6.0(Marshmallow)及更高版本中,当应用尝试将普通应用设置存储在安全设置(Secure Settings)区域时触发[^1][^2]。根本原因是Android系统对设置存储进行了严格分区: 1. **设置存储分区**: - `System Settings`:普通应用设置,通过`Settings.System`访问 - `Secure Settings`:设备安全相关设置,通过`Settings.Secure`访问 - `Global Settings`:系统级全局设置 2. **违规操作**: ```java // 错误示例:将普通设置存入安全区域 Settings.Secure.putString(getContentResolver(), "my_app_setting", "value"); ``` 3. **风险后果**: - Android 12+ 已将此警告升级为错误 - 可能导致设置无法保存或读取 - 应用在Android 12+设备上崩溃 --- ### 完整解决方案 #### 1. 迁移到正确存储位置 ```java // 迁移前(错误) Settings.Secure.putString(getContentResolver(), "theme_preference", "dark"); // 迁移后(正确) if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) { // 使用系统设置区域 Settings.System.putString(getContentResolver(), "theme_preference", "dark"); } else { // 旧版本回退方案 SharedPreferences prefs = getSharedPreferences("app_prefs", MODE_PRIVATE); prefs.edit().putString("theme_preference", "dark").apply(); } ``` #### 2. 使用SharedPreferences(推荐) ```java // 在Application类中初始化 public class MyApp extends Application { private static SharedPreferences sPrefs; @Override public void onCreate() { super.onCreate(); sPrefs = getSharedPreferences("app_settings", MODE_PRIVATE); } public static void saveSetting(String key, String value) { sPrefs.edit().putString(key, value).apply(); } } ``` #### 3. 安全设置的特殊处理 若确实需要访问安全设置(需系统权限): ```xml <!-- AndroidManifest.xml 添加权限 --> <uses-permission android:name="android.permission.WRITE_SECURE_SETTINGS"/> ``` ```java // 检查权限 if (Settings.Secure.canWrite(context)) { Settings.Secure.putString(resolver, Settings.Secure.LOCATION_PROVIDERS_ALLOWED, value); } else { // 引导用户到系统设置页 Intent intent = new Intent(Settings.ACTION_MANAGE_WRITE_SETTINGS); intent.setData(Uri.parse("package:" + context.getPackageName())); startActivity(intent); } ``` #### 4. 数据库迁移脚本 ```java public void migrateOldSettings(Context context) { ContentResolver resolver = context.getContentResolver(); // 从Secure读取旧设置 String oldValue = Settings.Secure.getString(resolver, "old_setting_key"); if (oldValue != null) { // 迁移到System区域 Settings.System.putString(resolver, "new_setting_key", oldValue); // 清除旧设置 Settings.Secure.putString(resolver, "old_setting_key", null); } } ``` #### 5. 兼容旧版本Android ```java public static void putAppSetting(ContentResolver resolver, String key, String value) { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) { Settings.System.putString(resolver, key, value); } else { // Android 5.1及以下使用兼容模式 try { Settings.System.putString(resolver, key, value); } catch (SecurityException e) { // 回退到SharedPreferences context.getSharedPreferences("legacy_prefs", 0) .edit().putString(key, value).apply(); } } } ``` --- ### 验证与测试方法 1. **日志检查**: ```bash adb logcat | grep -E 'SettingsProvider|Settings' ``` 2. **设置项验证**: ```bash # 检查系统设置 adb shell settings get system [your_setting_key] # 检查安全设置(需root) adb shell settings get secure [your_setting_key] ``` 3. **兼容性测试矩阵**: | Android版本 | 测试方案 | |------------|----------| | 5.0-5.1 (Lollipop) | 使用System设置 + SharedPreferences回退 | | 6.0-11 (Marshmallow+) | 严格使用System设置 | | 12+ (Snow Cone) | 完全禁用Secure设置存储 | --- ### 预防措施 1. **代码规范检查**: ```gradle // build.gradle 添加Lint检查 android { lintOptions { warning "SecureSettings" error "SecureSettings" } } ``` 2. **架构设计原则**: ```mermaid graph TD A[应用设置] --> B{需要系统级共享?} B -->|是| C[Settings.System] B -->|否| D[SharedPreferences] C --> E{涉及设备安全?} E -->|是| F[申请 WRITE_SECURE_SETTINGS 权限] E -->|否| G[直接使用 Settings.System] ``` 3. **持续监控**: ```java // 在Application中检测违规使用 public void onContentChanged() { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) { if (isUsingSecureSettings()) { reportToAnalytics("SecureSettings_Usage"); } } } ``` > **关键提示**:Android 12+ 已将此警告变为强制错误,建议在2023年底前完成所有迁移工作[^1][^2]。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值