最近遇到一个蛋疼的疑问就是读取Android 属性值,看到有人在代码中调用了Property.get()。盲人摸象了一把,从字面上看,以为Property.get()是读取Android 系统属性的方法,说白了以为他等同于getprop。然后自己很傻很天真的用了一把,发现坑爹的是木有出现自己想要的结果。后来查了下,才知道,这个是反映JAVA属性的方法,无法获取android 系统属性,也就是Build.prop system.prop这些内容的值。那么他读的是哪个地方的值呢。。。仔细看了下Property的包,是java.lang.system,于是开始找System.java,发现他的路径在Android libcore下面,然后打开这个System.java文件,猛然发现一块宝地:
/libcore/luni/system/main/java/java/lang/system.java
private static void initSystemProperties() { VMRuntime runtime = VMRuntime.getRuntime(); Properties p = new Properties(); String projectUrl = "http://www.android.com/"; String projectName = "The Android Project"; p.put("java.boot.class.path", runtime.bootClassPath()); p.put("java.class.path", runtime.classPath()); // None of these four are meaningful on Android, but these keys are guaranteed // to be present for System.getProperty. For java.class.version, we use the maximum // class file version that dx currently supports. p.put("java.class.version", "50.0"); p.put("java.compiler", ""); p.put("java.ext.dirs", ""); p.put("java.version", "0"); p.put("java.home", getenv("JAVA_HOME", "/system")); p.put("java.io.tmpdir", "/tmp"); p.put("java.library.path", getenv("LD_LIBRARY_PATH")); p.put("java.specification.name", "Dalvik Core Library"); p.put("java.specification.vendor", projectName); p.put("java.specification.version", "0.9"); p.put("java.vendor", projectName); p.put("java.vendor.url", projectUrl); p.put("java.vm.name", "Dalvik"); p.put("java.vm.specification.name", "Dalvik Virtual Machine Specification"); p.put("java.vm.specification.vendor", projectName); p.put("java.vm.specification.version", "0.9"); p.put("java.vm.vendor", projectName); p.put("java.vm.version", runtime.vmVersion()); p.put("file.separator", "/"); p.put("line.separator", "\n"); p.put("path.separator", ":"); p.put("java.runtime.name", "Android Runtime"); p.put("java.runtime.version", "0.9"); p.put("java.vm.vendor.url", projectUrl); p.put("file.encoding", "UTF-8"); p.put("user.language", "en"); p.put("user.region", "US"); p.put("user.home", getenv("HOME", "")); p.put("user.name", getenv("USER", "")); StructUtsname info = Libcore.os.uname(); p.put("os.arch", info.machine); ... }原来如此,兄弟们如果相用System.getProperty那只能输出这些字段中的一个了。如果有兄弟想加下新的字段,可以在这里加下,不过不推荐啊。。。这是坑爹的节奏。有没有更好的方式,还在研究。
如果想读取系统的属性值,看来只能用SystemProperties来搞了,关键坑爹的是找不到这个函数,如果我们在Eclipse里面直接写,后来去查Framework,才知道这个是个隐藏API,就是方法头上有个Hide的字样。怎么直接用了,只有一个方法,编译你的framework源码,然后把中间文件framework_intermidiate中的class.jar弄出来,再以库的形式加入到Eclipse工程中。搞定。。。。这个方法类似于shell中执行getprop命令。
如果兄弟们又问,那我想添加新的值到build.prop中呢,然后被getprop看到。额。。。。我所看到的有两种方式:
首先需要添加相应权限:
去到/system/core/init/property_service.c中添加相应规则
struct { const char *prefix; unsigned int uid; unsigned int gid; } property_perms[] = { { "net.rmnet0.", AID_RADIO, 0 }, { "net.gprs.", AID_RADIO, 0 }, { "net.ppp", AID_RADIO, 0 }, { "net.qmi", AID_RADIO, 0 }, { "net.lte", AID_RADIO, 0 }, { "net.cdma", AID_RADIO, 0 }, { "ril.", AID_RADIO, 0 }, { "gsm.", AID_RADIO, 0 }, { "persist.radio", AID_RADIO, 0 }, { "net.dns", AID_RADIO, 0 }, { "sys.usb.config", AID_RADIO, 0 }, { "net.", AID_SYSTEM, 0 }, { "dev.", AID_SYSTEM, 0 }, { "runtime.", AID_SYSTEM, 0 }, { "hw.", AID_SYSTEM, 0 }, { "sys.", AID_SYSTEM, 0 }, { "service.", AID_SYSTEM, 0 }, { "wlan.", AID_SYSTEM, 0 }, { "bluetooth.", AID_BLUETOOTH, 0 }, { "dhcp.", AID_SYSTEM, 0 }, { "dhcp.", AID_DHCP, 0 }, { "debug.", AID_SYSTEM, 0 }, { "debug.", AID_SHELL, 0 }, { "log.", AID_SHELL, 0 }, { "service.adb.root", AID_SHELL, 0 }, { "service.adb.tcp.port", AID_SHELL, 0 }, { "persist.sys.", AID_SYSTEM, 0 }, { "persist.service.", AID_SYSTEM, 0 }, { "persist.security.", AID_SYSTEM, 0 }, { "persist.service.bdroid.", AID_BLUETOOTH, 0 }, { "selinux." , AID_SYSTEM, 0 }, // Local add { "xxx.", AID_SYSTEM, 0 }, { "http.", AID_SYSTEM, 0 }, { "xxxx.media.", AID_MEDIA, 0 }, // local Patch End { NULL, 0, 0 } };然后。。。你可以
使用setprop来动态添加
或者可以找到自己产品的device.mk编译文件,找到PRODUCT_PROPERTY_OVERRIDES += XXXXX1\
XXXX2
或者不太推荐的方法:
buildinfo.sh中加入 echo "xxx.test.property" = 'welcome'"
真心蛋疼啊。。。。太不专业了,呵呵。