SystemProperties操作要点
Android9之后应用直接读取SystemProperties属性时会出现读取不到等现象。以读取SN为例,常用的读取方法有:
1.直接读取(比如依赖了framework.jar)
String sn = SystemProperties.get("ro.serialno", null);
2.反射调用
String sn = null;
try {
Class<?> c =Class.forName("android.os.SystemProperties");
Method get =c.getMethod("get", String.class);
sn = (String)get.invoke(c, "ro.serialno");
} catch (Exception e) {
e.printStackTrace();
}
3.android.os.Build属性或者方法
String sn = android.os.Build.SERIAL;
Android10之后可以使用以下方法
String sn = Build.getSerial();
但是最终均拿不到SN号,而从Build.getSerial()方法中可以看到针对此属性的获取需要一个系统应用权限:
@RequiresPermission(Manifest.permission.READ_PRIVILEGED_PHONE_STATE)
public static String getSerial() {
IDeviceIdentifiersPolicyService service = IDeviceIdentifiersPolicyService.Stub
.asInterface(ServiceManager.getService(Context.DEVICE_IDENTIFIERS_SERVICE));
try {
Application application = ActivityThread.currentApplication();
String callingPackage = application != null ? application.getPackageName() : null;
return service.getSerialForPackage(callingPackage, null);
} catch (RemoteException e) {
e.rethrowFromSystemServer();
}
return UNKNOWN;
}
这个权限属于系统应用权限“Permission is only granted to system apps”,也就是说在Android9以上,如果要读取到该属性的话需要系统级别的应用才可以。因此解决方法只能是升级应用等级为系统应用,以下两种方式择一即可:
方法一、声明为系统应用(使用系统签名):
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
android:sharedUserId="android.uid.system"
方法二、应用放在/system/priv-app/目录下
自定义属性写入异常
成为系统应用之后可以正常读取SystemProperties下的属性,但是要写入时需要注意属性权限,在/system/etc/selinux/plat_property_contexts文件(Android版本在N及N以前, 对应的文件路径是/property_contexts,从Android O开始,对应的文件路径是/system/etc/selinux/plat_property_contexts和/vendor/etc/selinux/nonplat_property_contexts)中定义了各个属性的写入权限情况,首先应用一旦成为系统应用那么就属于“system_prop”这个群组,而property_contexts中针对SystemProperties各个属性可以操作的群组做了明确的划分,如下部分:
ro.llk. u:object_r:llkd_prop:s0
ro.khungtask. u:object_r:llkd_prop:s0
log. u:object_r:log_prop:s0
log.tag u:object_r:log_tag_prop:s0
log.tag.WifiHAL u:object_r:wifi_log_prop:s0
security.perf_harden u:object_r:shell_prop:s0
service.adb.root u:object_r:shell_prop:s0
service.adb.tcp.port u:object_r:shell_prop:s0
persist.audio. u:object_r:audio_prop:s0
persist.bluetooth. u:object_r:bluetooth_prop:s0
persist.debug. u:object_r:persist_debug_prop:s0
persist.logd. u:object_r:logd_prop:s0
ro.logd. u:object_r:logd_prop:s0
persist.logd.security u:object_r:device_logging_prop:s0
persist.logd.logpersistd u:object_r:logpersistd_logging_prop:s0
logd.logpersistd u:object_r:logpersistd_logging_prop:s0
persist.log.tag u:object_r:log_tag_prop:s0
persist.mmc. u:object_r:mmc_prop:s0
persist.netd.stable_secret u:object_r:netd_stable_secret_prop:s0
persist.sys. u:object_r:system_prop:s0
persist.sys.safemode u:object_r:safemode_prop:s0
persist.sys.theme u:object_r:theme_prop:s0
当使用SystemProperties.set(key,val)设置一个前缀在property_contexts之外的key时,如:
SystemProperties.set("abc.test","123hhh");
那么会收到一个异常:
Unable to set property "abc.test" to "123hhh": error code: 0x18
这时主要在property_contexts中新增该属性的作用群组就可以了
abc.test u:object_r:system_prop:s0