1. 程式人生 > >Android SystemProperties.get()和System.getProperty()的區別

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

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'"

真心蛋疼啊。。。。太不專業了,呵呵。