**SystemProperties.java这个类是@hide的,**所以不对外公开,一般开发者是访问不到的,但是我们可以通过反射机制来使用。通过反射取得wifi的接口名为例!
<!-- 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.java
SystemProperties.java 在android源码的位置:frameworks/base/core/java/android/os/SystemProperties;
<!-- 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"
<!-- 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是一个结构体,具体定义,请参考
<!-- lang: cpp -->
#include "jni.h"
最后调用了 <!-- lang: cpp --> #include "android_runtime/AndroidRuntime.h"
中的方法:
<!-- lang: cpp -->
int register_android_os_SystemProperties(JNIEnv *env)
将本地方法注册到虚拟机中
接下来我们分析一下Android系统的Properties
有一些特殊命名的属性会有不同的效果
如ro.开头的属性是只读的
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 }
};