Android SystemProperties.get()和System.getProperty()的區別
最近遇到一個蛋疼的疑問就是讀取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
原來如此,兄弟們如果相用System.getProperty那隻能輸出這些欄位中的一個了。如果有兄弟想加下新的欄位,可以在這裡加下,不過不推薦啊。。。這是坑爹的節奏。有沒有更好的方式,還在研究。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); ... }
如果想讀取系統的屬性值,看來只能用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'"
真心蛋疼啊。。。。太不專業了,呵呵。