写了个 native 小工具,想读 ro.product.model 判断机型。property_get 返回 0,缓冲区里空的,logcat 也没有报错,代码看着没问题。

头文件、返回值和缓冲区

property_get 声明在 sys/system_properties.h,底层走 __system_property_get。返回值是字符串长度,属性不存在返回 0,不是 -1。缓冲区至少给 PROP_VALUE_MAX,也就是 92 字节,给 32 字节会截断。读之前把缓冲区清零,别拿上一次的内容当结果。

char value[PROP_VALUE_MAX] = {0}; int len = __system_property_get("ro.product.model", value);

读不到的五种原因

  • 属性名拼错:ro.product.model 和 ro.product.name 不是一个东西
  • SELinux 拦截:avc denied 会出现在 dmesg,普通域读不到系统属性
  • ro. 前缀只读:运行期改不了,只能刷 prop 或改 build.prop
  • 属性服务没起:早期启动阶段读不到,init 还没初始化完
  • 权限不足:非系统应用或非 root 进程读受限属性返回空

怎么验证

先在 adb shell 里 getprop ro.product.model,能读到说明属性存在,问题在进程权限。再 getenforce 看是不是 Enforcing,dmesg 里搜 avc。自己加的属性要在 property_contexts 里声明类型,否则 setprop 直接被拒。

写属性的注意点

property_set 只对可写前缀有效,persist. 开头的会落盘,ctl. 开头的是控制命令,别乱用。Android 8 之后对非系统分区的属性写入限制更严,能走配置文件就别在运行期改。改完用 getprop 回读确认,别只看返回值。

链接和兼容性

老代码链接 libcutils 才能用 property_get,新 NDK 建议直接调 bionic 的 __system_property_get,少一个依赖。Android 12 起部分接口有变化,编译报未定义符号时先查 NDK 版本和 minSdk。

读属性这事,先 getprop 验证,再查 SELinux,最后才怀疑代码。顺序反了会绕很久。