Android Settings中System/Global/Secure

一、 概述

在Android启动之后,我们通常需要根据自己的一些需要来设置一些符合我们使用习惯的属性。

例如:来电铃声、锁屏时间、日期格式等等。而这些属性的设置通常是有Settings为入口,通过SettingsProvider来进行的。SettingsProvider也是所有系统设置的管理者。

在M(Android5.0)版本之前,SettingsProvider中系统设置是存储在settings.db数据库中;但是在L(Android6.0)之后,SettingsProvider中系统设置改为由xml存储在data分区。

为什么要从settings.db改为xml存储?

原因:

1、这次修改涉及到了global,secure,system 三个表;并且实现方式从之前的数据库,改为异步性能更加优良的xml。
2、这次修改主要是基于性能的考量(写入一条耗时从400ms降低为10ms),同时也能够使得保存数据的过程更加可信。
3、实际上,得保存数据的过程更加可信这一条并不是问题的关键,写入失败的情况不仅非常罕见,而且上层应用修改SettingsProvider设置都是通过SettingsProvider来实现的。所以当上层APP下次再次启动的时候,并不知道数据写入失败。
4、改变SettingsProvider的实现方式(从db改为xml以及相应逻辑),可以有效的防止某些恶意APP监听某些设置选项,进而频繁的进行操作。
5、每个用户都有自己的一份SettingsProvider设置xml文档。通常位于/data/system/users/userid/
6、控制APP针对SettingsProvider的写入(合法性的判断)
7、控制SettingsProvider的大小(数据量大小,占用内存大小,etc.)

其实主要原因就是因为性能安全两个原因。

使用adb shell进入data分区中可以看到:
PS C:\Users\MAZHUANG> adb shell
xet509:/ # cd /data/system/users/0
xet509:/data/system/users/0 # ls -l
total 3108
-rw------- 1 system system   12962 2021-12-07 07:02 settings_global.xml
-rw------- 1 system system   11804 2021-12-05 14:16 settings_secure.xml
-rw------- 1 system system    6448 2021-12-04 17:54 settings_system.xml
xet509:/data/system/users/0 #

其中settings_global.xmlsettings_secure.xmlsettings_system.xml 、即对应/frameworks/base/core/java/android/provider/Settings.java中的三个内部类:Global、Secure、System。

也就是Settings的三种分类,分别如下:
  1. Global:所有的偏好设置对系统的所有用户公开,第三方APP有读没有写的权限;
  2. System:包含各种各样的用户偏好系统设置,第三方APP有读没有写的权限;
  3. Secure:安全性的用户偏好系统设置,第三方APP有读没有写的权限。

可以看到它们三个都继承了BaseColumns

    /*** System settings, containing miscellaneous system preferences.  This* table holds simple name/value pairs.  There are convenience* functions for accessing individual settings entries.*/public static final class System extends NameValueTable {// NOTE: If you add new settings here, be sure to add them to// com.android.providers.settings.SettingsProtoDumpUtil#dumpProtoSystemSettingsLocked.private static final float DEFAULT_FONT_SCALE = 1.0f;/*** The content:// style URL for this table*/public static final Uri CONTENT_URI =Uri.parse("content://" + AUTHORITY + "/system");private static final ContentProviderHolder sProviderHolder =new ContentProviderHolder(CONTENT_URI);private static final NameValueCache sNameValueCache = new NameValueCache(CONTENT_URI,CALL_METHOD_GET_SYSTEM,CALL_METHOD_PUT_SYSTEM,sProviderHolder);private static final HashSet<String> MOVED_TO_SECURE;................}/*** Secure system settings, containing system preferences that applications* can read but are not allowed to write.  These are for preferences that* the user must explicitly modify through the system UI or specialized* APIs for those values, not modified directly by applications.*/public static final class Secure extends NameValueTable {// NOTE: If you add new settings here, be sure to add them to// com.android.providers.settings.SettingsProtoDumpUtil#dumpProtoSecureSettingsLocked./*** The content:// style URL for this table*/public static final Uri CONTENT_URI =Uri.parse("content://" + AUTHORITY + "/secure");..........}/*** Global system settings, containing preferences that always apply identically* to all defined users.  Applications can read these but are not allowed to write;* like the "Secure" settings, these are for preferences that the user must* explicitly modify through the system UI or specialized APIs for those values.*/public static final class Global extends NameValueTable {// NOTE: If you add new settings here, be sure to add them to// com.android.providers.settings.SettingsProtoDumpUtil#dumpProtoGlobalSettingsLocked./*** The content:// style URL for global secure settings items.  Not public.*/public static final Uri CONTENT_URI = Uri.parse("content://" + AUTHORITY + "/global");/*** Whether users are allowed to add more users or guest from lockscreen.* <p>* Type: int* @hide*/public static final String ADD_USERS_WHEN_LOCKED = "add_users_when_locked";..........}

在Settings.java搜索NameValueTable可以看到:

    /*** Common base for tables of name/value settings.*/public static class NameValueTable implements BaseColumns {public static final String NAME = "name";public static final String VALUE = "value";protected static boolean putString(ContentResolver resolver, Uri uri,String name, String value) {// The database will take care of replacing duplicates.try {ContentValues values = new ContentValues();values.put(NAME, name);values.put(VALUE, value);resolver.insert(uri, values);return true;} catch (SQLException e) {Log.w(TAG, "Can't set key " + name + " in " + uri, e);return false;}}public static Uri getUriFor(Uri uri, String name) {return Uri.withAppendedPath(uri, name);}}

查看**/frameworks/base/core/java/android/provider/BaseColumns.java**可以看到:

package android.provider;public interface BaseColumns
{/*** The unique ID for a row.* <P>Type: INTEGER (long)</P>*/public static final String _ID = "_id";/*** The count of rows in a directory.* <P>Type: INTEGER</P>*/public static final String _COUNT = "_count";
}

这个类只是提供了两个字段,一个是"_id"一个是"_count",便于调用数据库时导致拼写错误,你也可以扩展它,或者自定义这么个,然后直接调用它的常量名,防止写sql语句时把列名拼错。

可以看出Settings中不论是Global、System还是Secure的数据都由键值对组成的。

SettingsProvider有点类似Android的properties系统(Android属性系统):SystemProperties

但是SettingsProvider和SystemProperties有以下不同点:

1、数据保存方式不同:SystemProperties的数据保存属性文件中(/system/build.prop等),开机后会被加载到system properties store;SettingsProvider的数据保存在文件/data/system/users/0/settings_***.xml和数据库settings.db中;
2、作用范围不同:SystemProperties可以实现跨进程、跨层次调用,即底层的c/c++可以调用,java层也可以调用;SettingProvider只能能在java层(APP)使用;
3、公开程度不同:SettingProvider有部分功能上层第三方APP可以使用(对于加了@hide标记的第三方APP仅可读,不可修改),SystemProperties上层第三方APP不可以使用。

二、关于Settings的修改方式:

通过adb shell进行修改:
PS C:\Users\MAZHUANG> adb shell
xet509:/ # settings put global audio_test_result 0
xet509:/ # settings get global audio_test_result
0
xet509:/ # settings list system
accelerometer_rotation=0
alarm_alert=content://media/internal/audio/media/210?title=Cesium&canonical=1
alarm_alert_set=1
background_power_saving_enable=1

可以看出主要格式为:

adb shell settings get [ global/system/secure ] [ key ]

adb shell settings put [ global/system/secure ] [ key ] [ value ]

adb shell settings list [ global/system/secure ]

通过java代码修改:(支持常用的String、int、boolean等类型的get和put)
Settings.Global.putString(mContext.getContentResolver(), "audio_test_result", value);//修改
Settings.Global.getString(mContext.getContentResolver(), "audio_test_result");//查询

常用的几个方法可以看Global/System/Secure中的几个方法(Global/System/Secure都有这个方法):

具体实现都在:/frameworks/base/core/java/android/provider/Settings.java**中

        /*** Look up a name in the database.* @param resolver to access the database with* @param name to look up in the table* @return the corresponding value, or null if not present*/public static String getString(ContentResolver resolver, String name) {return getStringForUser(resolver, name, resolver.getUserId());}/*** Store a name/value pair into the database.* @param resolver to access the database with* @param name to store* @param value to associate with the name* @return true if the value was set, false on database errors*/public static boolean putString(ContentResolver resolver, String name, String value) {return putStringForUser(resolver, name, value, resolver.getUserId());}

三、Settings中值的监听

有时需要监听Settings下面的值,这个时候可以通过ContentObserver 来监听值的变化。

1.首先自定义一个类继承ContentObserver。在onChange()方法里面再次去获取Settings的值。

    private final class SettingsAudioTestObserver extends ContentObserver {public SettingsAudioTestObserver(Handler handler) {super(handler);}@Overridepublic void onChange(boolean selfChange, android.net.Uri uri) {Log.d(TAG, " SettingsAudioTestObserver  onChange......" );int maudio = Settings.Global.getInt(mContext.getContentResolver(), Settings.Global.AUDIO_TEST_RESULT, 0);Log.d(TAG, " SettingsAudioTestObserver  onChanged  maudio====" + maudio);Log.d(TAG, " SettingsAudioTestObserver  onChanged  Integer.toString(maudio) start ====" + Integer.toString(maudio));if(maudio == 1){WriteFile(AUDIO_TEST_RESULT_PATH,"1");}else{WriteFile(AUDIO_TEST_RESULT_PATH,"0");}Log.d(TAG, " SettingsAudioTestObserver  onChanged  Integer.toString(maudio)  end ====" + Integer.toString(maudio));}}

2.注册监听。

    mHandler = new Handler(true /*async*/);mAudiotestobserver = new SettingsAudioTestObserver(mHandler);mContext.getContentResolver().registerContentObserver(Settings.Global.getUriFor(Settings.Global.AUDIO_TEST_RESULT), false, mAudiotestobserver, UserHandle.USER_ALL);

3.结束时候取消监听。

getContentResolver().unregisterContentObserver(mAudiotestobserver);

四、Settings常用之处

系统设置中很多设置其实都是存在Settings中的System、Global、Secure中

需要用到公共数据的时候也可以采用存在Settings中这种方法

可以对Settings中某个值进行监听,执行对应的操作等…

Android Settings中System/Global/Secure相关推荐

  1. Android开发:关于Android Settings中的八个问题

    本问将回答以下八个问题,如有错误,敬请批评指正,不胜感激!(注:本文中的Settings解析基于android4.0+) 问题一.Settings的主界面是怎么实现的? 问题二.为什么使用hierar ...

  2. Android Settings 中wifi详情页 隐私默认选中设备mac

    1.概述 在10.0的系统产品开发中,在对ota升级中,由于要固定使用本机mac地址,所以不能让选择默认mac地址,这时就要修改默认设置,保证升级能够成功 2.Settings 中wifi详情页 隐私 ...

  3. Android Settings中Preference的理解以及使用

    Preference 是Android App 中重要的控件之一,Settings 模块大部分都是通过 Preference 实现 优点: Preference 可以自动显示我们上次设置的数据,And ...

  4. 修改Android模拟器中System目录的内容(framework.jar)

    在做Android开发的时候,经常需要修改framework或是系统package里面的东西,如果没有硬件去的话,可以在模拟器上面去验证. 具体方法是,复制你所建立的模拟器版本的system.img到 ...

  5. Android settings中BT介绍

    一.蓝牙主要涉及到的类 1. BluetoothSettings.java 蓝牙配置和连接管理界面,就是咱们常见的蓝牙界面.它管理着蓝牙界面的加载,蓝牙搜索,蓝牙连接,蓝牙重命名等管理功能 2. Bl ...

  6. Android Settings中显示自定义dialog

    第一种方法,参照NightDisplaySettings.java @Overridepublic boolean onPreferenceTreeClick(Preference preferenc ...

  7. Settings provider system和global表格数据访问

    我们都知道Settings有system/ global和secure 三个表格,但是有没有发现,其实在读取3个表格数据时,并非仅仅从固定表格中读取,读取其中一个时,还会去读取另外2个,如果发现被挪到 ...

  8. android studio 前言中不允许有内容_Android Studio 中 System Trace 的新增功能

    在 Android Studio 4.0 中,我们已经对 CPU Profiler 的 UI 做了大量调整来提供更加直观的工作流记录,而在 Android Studio 4.1 中,我们基于开发者们的 ...

  9. vb.net中滚动条一直显示没有数据时也显示_Android Studio 中 System Trace 的新增功能...

    Android Studio 中 System Trace 的新增功能 在 Android Studio 4.0 中,我们已经对 CPU Profiler 的 UI 做了大量调整来提供更加直观的工作流 ...

最新文章

  1. LeetCode 41. First Missing Positive--Python 解法--数学题-找到不存在的最小正整数-O(1)空间复杂度
  2. python作图一览
  3. 掌握Tiles框架 (二)-- Tiles布局和定义
  4. 超长整数相加 c语言类,二个超长正整数的相加
  5. 解决TIME_WAIT过多造成的问题
  6. Javascript aop(面向切面编程)之around(环绕)
  7. 一个人的成功取决于晚上的8点至10点--经典语录必读
  8. 热点效应是指_热电偶的热电效应是什么意思 浅谈热电偶下的热点效应
  9. cocos2d-x返回Android游戏黑屏解决办法
  10. 栈(顺序存储)C++模板实现
  11. python程序启动其他python程序,如何使用Python启动应用程序的实例?
  12. matlab车辆测距,一种基于单目视觉的车辆测距方法
  13. rethat安装MySQL多例_SSM 使用 mybatis 分页插件 pagehepler 实现分页
  14. AndroidStudio编译引入JsonObject
  15. 【微波】【1】色散关系式与 TEM导波、TE导波、TM导波、混合波区别和特性
  16. 爱客影院自动采集源码v3.5.5
  17. Java面试题及答案整理
  18. 华为HCIP认证考试简介
  19. 自动化测试用例设计方法
  20. java if else 如何简化_if else 简化写法

热门文章

  1. k8s通过命令批量删除pod
  2. 【从零开始游戏开发】 开发环境准备 | Intellij idea 编辑器 | EmmyLua插件 | Unity引擎 | 编程语言
  3. 廖python入门视频_GitHub - aisuhua/codeparkshare: Python初学者(零基础学习Python、Python入门)书籍、视频、资料、社区推荐...
  4. 软件加密技术和注册机制
  5. 小程序中this.setData的使用和注意事项
  6. texworks注释掉多行latex代码。
  7. 解决:Word需要查找两个固定字符间的字符 Word将查找到的字符全部选中
  8. nfc怎么写入html,谈nfc电子标签的读取和写入方法
  9. ccitt crc16
  10. 一寸免冠照片是什么意思?如何才能制作或修改?