最近遇到一个蛋疼的疑问就是读取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'"
真心蛋疼啊。。。。太不专业了,呵呵。