**SystemProperties.java這個類是@hide的,**因此不對外公開,通常開發者是訪問不到的,可是咱們能夠經過反射機制來使用。經過反射取得wifi的接口名爲例!java
<!-- lang: java --> public class SystemInfo{ private Method methodGetProperty; private static SystemInfo instance = new SystemInfo(); public static SystemInfo getInstance() { return instance; } private SystemInfo(){ Class classSystemProperties = Class.forName("android.os.SystemProperties"); methodGetProperty = classSystemProperties.getMethod("get", String.class); } public String getProperty(String property) { if(methodGetProperty == null) return null; try { return (String)methodGetProperty.invoke(null, property); } catch(IllegalAccessException e) { Log.w(TAG, "Failed to get property"); } catch(InvocationTargetException e) { Log.w(TAG, "Exception thrown while getting property"); } return null; } public static void main() { String interfaceName = SystemInfo.getInstance().getProperty("wifi.interface"); } }
下面經過Android源碼講解SystemProperties.javaandroid
SystemProperties.java 在android源碼的位置:frameworks/base/core/java/android/os/SystemProperties;shell
<!-- lang: java --> public class SystemProperties { public static final int PROP_NAME_MAX = 31; public static final int PROP_VALUE_MAX = 91; private static native String native_get(String key); private static native String native_get(String key, String def); private static native int native_get_int(String key, int def); private static native long native_get_long(String key, long def); private static native boolean native_get_boolean(String key, boolean def); private static native void native_set(String key, String def); public static String get(String key) { if (key.length() > PROP_NAME_MAX) { throw new IllegalArgumentException("key.length > " + PROP_NAME_MAX); } return native_get(key); } public static String get(String key, String def) { if (key.length() > PROP_NAME_MAX) { throw new IllegalArgumentException("key.length > " + PROP_NAME_MAX); } return native_get(key, def); } }
這邊使用JNI調用了本地方法,這些方法位於:"frameworks/base/core/jni/android_os_SystemProperties.cpp"app
<!-- lang: cpp --> #include "cutils/properties.h" #include "jni.h" #include "android_runtime/AndroidRuntime.h" #include <nativehelper/JNIHelp.h> namespace android { static jstring SystemProperties_getSS(JNIEnv *env, jobject clazz, jstring keyJ, jstring defJ) { int len; const char* key; char buf[PROPERTY_VALUE_MAX]; jstring rvJ = NULL; if (keyJ == NULL) { jniThrowNullPointerException(env, "key must not be null."); goto error; } key = env->GetStringUTFChars(keyJ, NULL); len = property_get(key, buf, ""); if ((len <= 0) && (defJ != NULL)) { rvJ = defJ; } else if (len >= 0) { rvJ = env->NewStringUTF(buf); } else { rvJ = env->NewStringUTF(""); } env->ReleaseStringUTFChars(keyJ, key); error: return rvJ; } static jstring SystemProperties_getS(JNIEnv *env, jobject clazz, jstring keyJ) { return SystemProperties_getSS(env, clazz, keyJ, NULL); } static JNINativeMethod method_table[] = { { "native_get", "(Ljava/lang/String;)Ljava/lang/String;", (void*) SystemProperties_getS }, { "native_get", "(Ljava/lang/String;Ljava/lang/String;)Ljava/lang/String;", (void*) SystemProperties_getSS }, { "native_get_int", "(Ljava/lang/String;I)I", (void*) SystemProperties_get_int }, { "native_get_long", "(Ljava/lang/String;J)J", (void*) SystemProperties_get_long }, { "native_get_boolean", "(Ljava/lang/String;Z)Z", (void*) SystemProperties_get_boolean }, { "native_set", "(Ljava/lang/String;Ljava/lang/String;)V", (void*) SystemProperties_set }, }; int register_android_os_SystemProperties(JNIEnv *env) { return AndroidRuntime::registerNativeMethods( env, "android/os/SystemProperties", method_table, NELEM(method_table)); } };
其中JNINativeMethod是一個結構體,具體定義,請參考tcp
<!-- lang: cpp --> #include "jni.h"
最後調用了 <!-- lang: cpp --> #include "android_runtime/AndroidRuntime.h"
中的方法:ionic
<!-- lang: cpp --> int register_android_os_SystemProperties(JNIEnv *env)
將本地方法註冊到虛擬機中ide
接下來咱們分析一下Android系統的Propertiesui
有一些特殊命名的屬性會有不一樣的效果spa
如ro.開頭的屬性是隻讀的debug
persist.開頭的屬性,即便重啓手機,仍然會存在
Android 的系統屬性包括兩部分:文件保存的持久屬性和每次開機導入的cache屬性。前者主要保存在下面幾個文件中(列出部分):
bionic/libc/include/sys/_system_properties.h
<!-- lang: cpp --> #define PROP_SERVICE_NAME "property_service" #define PROP_PATH_RAMDISK_DEFAULT "/default.prop" #define PROP_PATH_SYSTEM_BUILD "/system/build.prop" #define PROP_PATH_SYSTEM_DEFAULT "/system/default.prop" #define PROP_PATH_LOCAL_OVERRIDE "/data/local.prop"
system/core/include/private/android_filesystem_config.h
<!-- lang: cpp --> #define AID_ROOT 0 /* traditional unix root user */ #define AID_SYSTEM 1000 /* system server */ #define AID_RADIO 1001 /* telephony subsystem, RIL */ #define AID_DHCP 1014 /* dhcp client */ #define AID_SHELL 2000 /* adb and debug shell user */ #define AID_CACHE 2001 /* cache access */ #define AID_APP 10000 /* first app user */
system/core/init/property_service.c
系統屬性的命名必須如下面這些字段開頭,不一樣的字段須要不一樣的權限:
<!-- lang: cpp --> 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 }, { "dhcp.", AID_SYSTEM, 0 }, { "dhcp.", AID_DHCP, 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 }, { NULL, 0, 0 } };