解决Android 11 获取不到Serial number方法

由于从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字段的包名进行判断即可。至此结束,每天成长一点就是最好的,加油自己!

你可能感兴趣的:(android)