由于从Android10开始采用沙盒存储模式以及权限策略的更新,导致适配的过程中获取不到种种的问题。由此分析下获取不到序列号的方法思路:
一、R的适配
1.从8.0开始获取SN的方法就是如下代码:
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) {
serialNumber = Build.getSerial();
LOGE.E("serialNumber + " + serialNumber);
}
然而,通过该方法在11上还是不奏效。
2.点击 serialNumber = Build.getSerial();方法中的Build查看了下源码,需要申请以下权限,
android.permission.READ_PHONE_STATE
经过申请权限后还是不能获取。。。。
3.紧接着,去看下系统源码,先查看了frameworks/base/core/java/android/os/Build.java,其中代码有以下定义。最主要的是IDeviceIdentifiersPolicyService对其获取的定义。
@SuppressAutoDoc // No support for device / profile owner.
@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;
}
4.跟踪源码一路看下去。
frameworks/base/services/core/java/com/android/server/os/DeviceIdentifiersPolicyService.java
@Override
public @Nullable String getSerial() throws RemoteException {
// Since this invocation is on the server side a null value is used for the
// callingPackage as the server's package name (typically android) should not be used
// for any device / profile owner checks. The majority of requests for the serial number
// should use the getSerialForPackage method with the calling package specified.
if (!TelephonyPermissions.checkCallingOrSelfReadDeviceIdentifiers(mContext,
/* callingPackage */ null, null, "getSerial")) {
return Build.UNKNOWN;
}
return SystemProperties.get("ro.serialno", Build.UNKNOWN);
}
@Override
public @Nullable String getSerialForPackage(String callingPackage,
String callingFeatureId) throws RemoteException {
if (!TelephonyPermissions.checkCallingOrSelfReadDeviceIdentifiers(mContext,
callingPackage, callingFeatureId, "getSerial")) {
return Build.UNKNOWN;
}
return SystemProperties.get("ro.serialno", Build.UNKNOWN);
}
此时,你会发现对与SN号的获取有这个两个方法限制,造成获取时一直是UNKNOWN的状态。如果,粗暴点修改让应用获取到SN号那就直接注释以下代码:
public @Nullable String getSerialForPackage(String callingPackage,
String callingFeatureId) throws RemoteException {
// if (!TelephonyPermissions.checkCallingOrSelfReadDeviceIdentifiers(mContext,
// callingPackage, callingFeatureId, "getSerial")) {
// return Build.UNKNOWN;
// }
return SystemProperties.get("ro.serialno", Build.UNKNOWN);
}
}
如若,合理美观只让特定的应用获取就需要对callingPackage字段的包名进行判断即可。至此结束,每天成长一点就是最好的,加油自己!