Android 系统属性添加篇
添加属性,存储值实现
文章目录
- 前言 - 需求
- 参考资料
- 一、添加属性文件
- 1、在 .mk 文件中添加系统属性 (System Property)
- 系统属性基础知识
- 定义说明-是什么
- 如何添加
- 属性前缀说明
- 优劣分析
- 2、在 SettingsProvider 数据库中添加设置 (Settings.Global/Secure/System)
- 定义说明-是什么
- 如何添加
- 插入数据库
- 定义键名
- 优劣分析
- 3、对比总结与如何选择
- 二、案例实战-添加系统属性
- 找到.mk 修改的位置并配置属性
- 三、读取系统属性-SystemProperties
- 源码查看
- 读取方法
- 总结
前言 - 需求
实现添加属性的功能,了解属性添加机制,搞明白两种不同的添加方式和区别
参考资料
Android系统开发入门-3.添加系统属性
Framework 层Settings.System, Settings.Secure和Settings.Global存储及应用
RK-Android11-系统增加一个属性值
一、添加属性文件
比如我们在windows
电脑上面 cmd
, getprop
获取到的属性 哪里来的? 这个需要搞清楚,如果我们把数据保存到我们看到的属性 getprop
里面的 key
对应的结果里面。
那么首先要解决的就是属性定义和属性配置,其次就是属性赋值来存储设置的值
比如如下 获取的属性:
1、在 .mk 文件中添加系统属性 (System Property)
这是底层系统级别的配置。
系统属性基础知识
定义说明-是什么
系统属性是Android
系统的一个全局键值对数据库,主要用于原生层(C/C++/Native
) 和 系统服务 之间的配置和通信。它通过 libcutils
库的 property_get
和 property_set
函数来访问。常见的例子如ro.product.model
(只读产品型号)、persist.sys.timezone
(持久化时区)、ctl.start/ctl.stop
(控制服务)。
如何添加
在 .mk
文件(通常是 device/<厂商>/<平台>/device.mk
)中,使用 PRODUCT_PROPERTY_OVERRIDES
变量来定义或覆盖系统属性的默认值
# 定义一个只读属性,通常在编译时确定
PRODUCT_PROPERTY_OVERRIDES += ro.vendor.my_custom_feature=enabled# 定义一个可读写并持久化的属性初始值
PRODUCT_PROPERTY_OVERRIDES += persist.vendor.sys.debug_log=0
属性前缀说明
ro
.:只读。一旦设置,值不能改变。persist
.:持久化。设置后会被保存到/data/property
目录,重启后依然有效。vendor./ctl.
等:其他前缀,没有特殊功能,主要用于命名空间分类。
优劣分析
优点
底层高效:直接在Native层读写,速度非常快,被大量用于系统初始化流程。
全局可见:所有进程(Java和Native
)都可以读取。
启动顺序早:在 init
进程解析 init.rc
时就可使用,非常适合控制底层服务和守护进程的启动行为。
权限控制:设置属性需要特定的SELinux
权限,相对安全。
缺点
- 类型单一:只支持字符串值,应用层需要自己解析(如将 “1” 解析为 true)。
- 不适合应用层大量使用:设计初衷并非用于应用配置,API设计也不友好(需要处理字符串)。
- 写入权限严格:非系统级应用通常无法设置大多数属性,需要配置SELinux策略。
2、在 SettingsProvider 数据库中添加设置 (Settings.Global/Secure/System)
这是上层应用框架级别的配置。
定义说明-是什么
Android
提供了一个名为 SettingsProvider
的系统应用,它维护了三个SQLite
数据库来为其他应用存储配置信息。这些配置通过Content Provider
暴露出来,供应用通过 Settings API
进行访问。
Global (Settings.Global)
: 所有用户共享的全局设置,通常需要系统权限(WRITE_SECURE_SETTINGS
)才能修改。例如,设备名称、USB调试开关。Secure (Settings.Secure)
: 每个用户的安全敏感设置。修改通常也需要系统权限。例如,默认输入法、受信任的凭据。System (Settings.System)
: 每个用户的非敏感系统偏好设置。普通应用(在同一用户下)也可以读写自己的包名相关的设置。例如,屏幕亮度、铃声选择。
如何添加
在frameworks/base/packages/SettingsProvider/res/values/defaults.xml
中添加条目的默认值。
<resources>...<!-- 在 defaults.xml 中 --><string name="def_my_custom_setting" translatable="false">default_value</string><integer name="def_my_custom_int_setting">1</integer><bool name="def_my_custom_bool_setting">true</bool>
</resources>
插入数据库
frameworks/base/packages/SettingsProvider/src/com/android/providers/settings/DatabaseHelper.java
的 loadGlobalSettings
, loadSecureSettings
, 或 loadSystemSettings
方法中,将默认值插入到对应的数据库表中。
// 在 DatabaseHelper.java 的 loadGlobalSettings 方法中
loadStringSetting(stmt, Settings.Global.MY_CUSTOM_SETTING,R.string.def_my_custom_setting);
loadIntegerSetting(stmt, Settings.Global.MY_CUSTOM_INT_SETTING,R.integer.def_my_custom_int_setting);
定义键名
在 frameworks/base/core/java/android/provider/Settings.java
中为你的新设置定义一个公开的静态常量 String
。
public static final String MY_CUSTOM_SETTING = "my_custom_setting";
优劣分析
优点:
-
类型丰富:支持
String, Int, Float, Long
等多种数据类型,应用层使用方便。 -
API
友好:提供了标准、易用的CRUD API (Settings.System.putInt(), Settings.Secure.getString()
等)。 -
权限模型清晰:通过
Android
标准的权限机制控制访问,管理方便。 -
面向应用层:是应用和系统服务保存和读取配置的首选方式。
缺点:
-
启动时机较晚:需要等
SettingsProvider
这个系统应用启动并加载数据库完成后才能使用,不能在非常早期的启动阶段(如init
阶段)依赖。 -
性能开销:基于
Content Provider
的数据库操作,比直接读写内存中的系统属性要慢。 -
对
Native
层不友好:Native
代码访问Settings
数据库比较麻烦,需要通过JNI
调用Java API
或直接查询SQLite
。
3、对比总结与如何选择
特性 | 系统属性 (System Property) | Settings 数据库 (Settings.Global/Secure/System) |
---|---|---|
层级 | 底层 (Init, Native) | 上层 (Framework, App) |
存储机制 | 内存映射文件 (/dev/properties) | SQLite 数据库 |
数据类型 | 仅字符串 | String, Int, Float, Long, Bool |
访问API | SystemProperty.get()/set() (Java), property_get()/set() (C++) | Settings.Global/Secure/System.getXXX()/putXXX() |
权限控制 | SELinux 策略 | Android 权限 (e.g., WRITE_SECURE_SETTINGS) |
持久化 | 需显式使用 persist. 前缀 | 自动持久化 |
启动阶段 | 非常早 (Init 阶段) | 较晚 (After SettingsProvider 启动) |
适用场景 | 控制底层服务、驱动参数、早期启动配置 | 应用偏好、用户设置、系统功能开关 |
二、案例实战-添加系统属性
比如我在系统里面添加几个属性 通过系统属性方式实现,如下:那么如何实现
[persist.fise.custom.usbdata]: [0]
[persist.fise.custom.usbmode]: [0]
[persist.fise.custom.wifidata]: [0]
[persist.fise.custom.wifimode]: [0]
找到.mk 修改的位置并配置属性
强烈建议先看看参考资料,或者 网上一些资料,然后自己去找配置文件,或者 在源码里面通过指定的key 来搜索配置文件.mk 位置。
Android系统开发入门-3.添加系统属性
RK-Android11-系统增加一个属性值
比如如下,通过属性:persist.sys.boot.reason
在源码里面查找,找到了配置文件.mk 位置,然后根据已有的写法配置自己的 属性
编译后,查看是否成功,如下:显示已经成功了的
三、读取系统属性-SystemProperties
前面是设置系统属性,如何读取呢?
源码查看
源码位置: /frameworks/base/core/java/android/os/SystemProperties.java
源码如下:
/** Copyright (C) 2019 The Android Open Source Project** Licensed under the Apache License, Version 2.0 (the "License");* you may not use this file except in compliance with the License.* You may obtain a copy of the License at** http://www.apache.org/licenses/LICENSE-2.0** Unless required by applicable law or agreed to in writing, software* distributed under the License is distributed on an "AS IS" BASIS,* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.* See the License for the specific language governing permissions and* limitations under the License.*/package android.os;// Stub for cutting dependency from sysprop_library to framework.jar
public class SystemProperties {public static String get(String key) {return null;}public static void set(String key, String val) {}private SystemProperties() {}
}
读取方法
直接看看系统读取方法,参考:
总结
为什么再次罗列属性添加、读取 基本知识点? 实际开发中太多数据持久化的知识点运用了,为快速开发提炼基本知识技能。