Android 系统属性 prop 读写:自定义系统参数、固件配置参数持久保存

发布时间:2026/7/26 23:32:05
Android 系统属性 prop 读写:自定义系统参数、固件配置参数持久保存 Android 系统属性 prop 读写自定义系统参数、固件配置参数持久保存工控设备开机要记住上次配置——IP 地址、波特率、传感器校准值。靠 SharedPreferences 不够硬核系统属性 prop 才是固件级的刻入DNA方案。一、Android 系统属性机制简介1.1 prop 是什么Android 系统属性System Property是一套全局的键值对key-value存储机制运行在 native 层由属性服务Property Service统一管理。它有以下几个特点全局共享所有进程都能读取跨进程无需 IPC内存存储属性值存在共享内存中读取速度极快部分持久化带persist.前缀的属性会写入文件重启不丢失类型单一只能存储字符串数字也得存成字符串简单理解prop 就是一个系统级的 HashMap所有 app 都能读只有特定权限才能写。1.2 persist 前缀的含义属性名前缀决定了它的行为前缀持久化重启后写入权限persist.✅ 写入/data/property/persistent_properties保留system/rootpersist.sys.✅ 同上保留system/rootro.❌ 只读属性保留编译时写入不可修改sys.❌ 仅内存丢失systemvendor.❌ 仅内存丢失vendordebug.❌ 仅内存丢失systemro.开头read-only编译时定死运行时不可修改如ro.product.modelpersist.开头可修改且持久化重启后值依然存在其他前缀可修改但不持久化重启后恢复默认工控固件配置必须用persist.前缀否则设备一断电配置就没了。二、常用系统属性查看与修改2.1 getprop 命令通过 adb shell 查看系统属性# 查看所有属性getprop# 查看指定属性getprop ro.product.model getprop ro.build.version.release# 查看带前缀的所有属性getprop|greppersist.常用属性一览属性名含义ro.product.model设备型号ro.build.version.releaseAndroid 版本号ro.build.version.sdkSDK 版本号ro.serialno设备序列号ro.bootmode启动模式persist.sys.locale系统语言persist.sys.timezone时区persist.sys.usb.configUSB 模式adb/mtp2.2 setprop 命令修改属性值需要 root 或系统权限# 设置属性setprop persist.sys.locale zh-CN# 设置自定义工控属性setprop persist.serial.baudrate115200setprop persist.serial.device /dev/ttyS1# 删除持久化属性设为空字符串即可setprop persist.myconfigsetprop在普通 app 进程中执行不了需要 adb root 或在系统源码中通过property_set()调用。三、Android 源码中属性定义3.1 build.prop 与 system.propAndroid 编译时属性来源有多个文件文件路径说明build/tools/buildinfo.sh生成基础 build.propdevice/vendor/device/system.prop设备厂商自定义属性system/property_contexts属性 SELinux 上下文定义default.prop/prop.default编译时注入的默认属性最终编译输出到设备上的/system/build.prop、/vendor/build.prop、/odm/build.prop。3.2 在源码中添加自定义属性在设备目录下创建或编辑system.prop# 工控板串口配置 persist.serial.baudrate9600 persist.serial.databits8 persist.serial.paritynone persist.serial.stopbits1 # 网关配置 persist.gateway.server_ip192.168.1.100 persist.gateway.server_port8080 persist.gateway.protocoltcp # 传感器校准 persist.sensor.temp_offset0.0 persist.sensor.humi_offset0.03.3 property_service 的写入限制不是什么属性都能随便写的。属性服务在property_service.cpp中定义了属性写入权限白名单// system/core/init/property_service.cppstaticconststruct{constchar*prefix;unsignedintuid;unsignedintgid;}property_perms[]{{net.rmnet0.,AID_RADIO,0},{net.gprs.,AID_RADIO,0},{net.ppp.,AID_ROOT,0},{persist.sys.,AID_SYSTEM,0},{persist.service.,AID_SYSTEM,0},{persist.,AID_SYSTEM,0},// persist.* 需要system权限{sys.,AID_SYSTEM,0},// ...};要点persist.*属性写入需要system UID即系统应用普通第三方 app 无法直接setprop需要将 app 签名为平台签名platform.pk8platform.x509.pem四、APP 中读写系统属性SystemProperties 反射调用Android 隐藏了SystemProperties类hideAPI普通 app 无法直接调用但可以通过反射访问。4.1 SystemProperties 反射封装publicclassSystemPropUtils{privatestaticClass?sSystemPropertiesClass;privatestaticMethodsGetMethod;privatestaticMethodsSetMethod;privatestaticMethodsGetIntMethod;privatestaticMethodsGetBooleanMethod;static{try{sSystemPropertiesClassClass.forName(android.os.SystemProperties);sGetMethodsSystemPropertiesClass.getMethod(get,String.class);sSetMethodsSystemPropertiesClass.getMethod(set,String.class,String.class);sGetIntMethodsSystemPropertiesClass.getMethod(getInt,String.class,int.class);sGetBooleanMethodsSystemPropertiesClass.getMethod(getBoolean,String.class,boolean.class);}catch(Exceptione){e.printStackTrace();}}/** * 读取字符串属性 */publicstaticStringget(Stringkey,Stringdef){try{return(String)sGetMethod.invoke(null,key);}catch(Exceptione){returndef;}}/** * 读取整型属性 */publicstaticintgetInt(Stringkey,intdef){try{return(int)sGetIntMethod.invoke(null,key,def);}catch(Exceptione){returndef;}}/** * 读取布尔属性 */publicstaticbooleangetBoolean(Stringkey,booleandef){try{return(boolean)sGetBooleanMethod.invoke(null,key,def);}catch(Exceptione){returndef;}}/** * 写入属性需要system权限 */publicstaticvoidset(Stringkey,Stringvalue){try{sSetMethod.invoke(null,key,value);}catch(Exceptione){e.printStackTrace();}}}4.2 工控固件配置管理完整示例publicclassFirmwareConfigManager{// 属性Key定义publicstaticfinalStringKEY_SERIAL_BAUDRATEpersist.serial.baudrate;publicstaticfinalStringKEY_SERIAL_DEVICEpersist.serial.device;publicstaticfinalStringKEY_GATEWAY_IPpersist.gateway.server_ip;publicstaticfinalStringKEY_GATEWAY_PORTpersist.gateway.server_port;publicstaticfinalStringKEY_GATEWAY_PROTOCOLpersist.gateway.protocol;publicstaticfinalStringKEY_SENSOR_TEMP_OFFSETpersist.sensor.temp_offset;publicstaticfinalStringKEY_DEVICE_IDpersist.device.id;// 默认值privatestaticfinalintDEFAULT_BAUDRATE9600;privatestaticfinalStringDEFAULT_SERIAL_DEVICE/dev/ttyS1;privatestaticfinalStringDEFAULT_GATEWAY_IP192.168.1.100;privatestaticfinalintDEFAULT_GATEWAY_PORT8080;privatestaticfinalStringDEFAULT_PROTOCOLtcp;privatestaticvolatileFirmwareConfigManagersInstance;privateFirmwareConfigManager(){}publicstaticFirmwareConfigManagergetInstance(){if(sInstancenull){synchronized(FirmwareConfigManager.class){if(sInstancenull){sInstancenewFirmwareConfigManager();}}}returnsInstance;}// 串口配置 publicintgetSerialBaudrate(){returnSystemPropUtils.getInt(KEY_SERIAL_BAUDRATE,DEFAULT_BAUDRATE);}publicvoidsetSerialBaudrate(intbaudrate){SystemPropUtils.set(KEY_SERIAL_BAUDRATE,String.valueOf(baudrate));}publicStringgetSerialDevice(){returnSystemPropUtils.get(KEY_SERIAL_DEVICE,DEFAULT_SERIAL_DEVICE);}publicvoidsetSerialDevice(Stringdevice){SystemPropUtils.set(KEY_SERIAL_DEVICE,device);}// 网关配置 publicStringgetGatewayIp(){returnSystemPropUtils.get(KEY_GATEWAY_IP,DEFAULT_GATEWAY_IP);}publicvoidsetGatewayIp(Stringip){SystemPropUtils.set(KEY_GATEWAY_IP,ip);}publicintgetGatewayPort(){returnSystemPropUtils.getInt(KEY_GATEWAY_PORT,DEFAULT_GATEWAY_PORT);}publicvoidsetGatewayPort(intport){SystemPropUtils.set(KEY_GATEWAY_PORT,String.valueOf(port));}// 传感器校准 publicfloatgetTempOffset(){StringvalSystemPropUtils.get(KEY_SENSOR_TEMP_OFFSET,0.0);returnFloat.parseFloat(val);}publicvoidsetTempOffset(floatoffset){SystemPropUtils.set(KEY_SENSOR_TEMP_OFFSET,String.valueOf(offset));}// 设备ID publicStringgetDeviceId(){returnSystemPropUtils.get(KEY_DEVICE_ID,UNKNOWN);}publicvoidsetDeviceId(Stringid){SystemPropUtils.set(KEY_DEVICE_ID,id);}/** * 打印当前所有配置调试用 */publicvoidprintAllConfig(){Log.i(FirmwareConfig, 工控固件配置 );Log.i(FirmwareConfig,串口设备: getSerialDevice());Log.i(FirmwareConfig,波特率: getSerialBaudrate());Log.i(FirmwareConfig,网关IP: getGatewayIp());Log.i(FirmwareConfig,网关端口: getGatewayPort());Log.i(FirmwareConfig,通信协议: SystemPropUtils.get(KEY_GATEWAY_PROTOCOL,DEFAULT_PROTOCOL));Log.i(FirmwareConfig,温度偏移: getTempOffset());Log.i(FirmwareConfig,设备ID: getDeviceId());}}在 Activity 中使用publicclassConfigActivityextendsAppCompatActivity{privateFirmwareConfigManagermConfig;OverrideprotectedvoidonCreate(BundlesavedInstanceState){super.onCreate(savedInstanceState);setContentView(R.layout.activity_config);mConfigFirmwareConfigManager.getInstance();mConfig.printAllConfig();// 读取配置填充UIetBaudrate.setText(String.valueOf(mConfig.getSerialBaudrate()));etGatewayIp.setText(mConfig.getGatewayIp());etGatewayPort.setText(String.valueOf(mConfig.getGatewayPort()));// 保存按钮btnSave.setOnClickListener(v-{mConfig.setSerialBaudrate(Integer.parseInt(etBaudrate.getText().toString()));mConfig.setGatewayIp(etGatewayIp.getText().toString());mConfig.setGatewayPort(Integer.parseInt(etGatewayPort.getText().toString()));Toast.makeText(this,配置已保存重启后生效,Toast.LENGTH_SHORT).show();});}}五、工控固件配置持久化方案对比方案持久化跨进程权限要求适用场景System Properties (persist.)✅✅ 全局system 签名固件级全局配置SharedPreferences✅❌ 仅本app无app 内部配置文件存储 (JSON/Properties)✅需自行处理文件权限大数据量配置SQLite✅需自行处理无结构化历史数据Settings.Global✅✅WRITE_SETTINGS系统级简单配置5.1 选择建议全局固件配置串口参数、网关地址→ 用persist.属性native 层和 Java 层都能读App 内部偏好界面主题、提醒开关→ 用 SharedPreferences大量历史数据采集记录、报警日志→ 用 SQLite 或文件需要 native 层读取的参数→ 必须用 propSharedPreferences 在 native 层读不了prop 的最大优势是跨语言——C/C 层用property_get()读Java 层用SystemProperties.get()读Shell 用getprop读三端共享同一份数据。这是其他方案做不到的。六、常见工控 prop 属性汇总属性名类型说明默认值persist.serial.baudrateint串口波特率9600persist.serial.devicestring串口设备节点/dev/ttyS1persist.serial.paritystring校验方式nonepersist.gateway.server_ipstring网关服务器IP192.168.1.100persist.gateway.server_portint网关端口8080persist.gateway.protocolstring通信协议tcppersist.gateway.reconnect_intervalint重连间隔(ms)5000persist.device.idstring设备唯一标识-persist.device.locationstring设备安装位置-persist.sensor.temp_offsetfloat温度校准偏移0.0persist.sensor.humi_offsetfloat湿度校准偏移0.0persist.gpio.relay_defaultint继电器默认状态0persist.net.eth_ipstring以太网静态IP192.168.1.88persist.net.eth_gatewaystring以太网网关192.168.1.1persist.net.eth_netmaskstring以太网掩码255.255.255.0persist.watchdog.enableboolean看门狗使能truepersist.watchdog.timeoutint看门狗超时(s)306.1 native 层读写属性C/C#includecutils/properties.h// 读取属性charvalue[92]{0};intretproperty_get(persist.serial.baudrate,value,9600);// ret 0 表示读取成功value 为属性值// 写入属性需要对应权限property_set(persist.serial.baudrate,115200);在 native 服务进程中直接调property_get/property_set即可读写同一份属性数据与 Java 层完全同步。6.2 通过 init.rc 设置默认值在init.rc中可以在启动时设置属性默认值on boot# 设置工控默认配置setprop persist.serial.baudrate9600setprop persist.serial.device /dev/ttyS1 setprop persist.gateway.reconnect_interval5000setprop persist.watchdog.enable1注意setprop只在属性不存在时设置默认值才有意义。已存在的persist.属性重启后不会覆盖会保留上次的值。如果需要强制重置可以在 init.rc 中先setprop persist.xxx 再设默认值——但这会清除用户配置慎用。系统属性是 Android 工控开发中最高效的全局配置方案。掌握 prop 的定义、读写、持久化机制就能实现固件级参数管理native 层和 Java 层共享配置断电不丢失跨进程零成本读取。这在定制固件、设备量产、远程运维等场景中是不可替代的能力。

相关新闻

最新新闻

日新闻

周新闻

月新闻