Android11 授权应用获取IMEI号和ICCID

这篇具有很好参考价值的文章主要介绍了Android11 授权应用获取IMEI号和ICCID。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

在Android11上获取IMEI号等设备信息需要android.permission.READ_PRIVILEGED_PHONE_STATE权限,而这个权限又只授予系统级应用。项目中如果targetSdkVersion值小于29获取到的是null,大于28报SecurityException错误。

1.获取ICCID
 public String getICCID(Context context) {
	TelephonyManager tm = (TelephonyManager) context.getSystemService(Context.TELEPHONY_SERVICE);
	String simSerialNumber = telephonyManager.getSimSerialNumber();
	return simSerialNumber;
 }

 或者

 public static String getICCID(Context context) {
    String iccid;
    TelephonyManager tm = (TelephonyManager) context.getSystemService(Context.TELEPHONY_SERVICE);
    iccid = tm.getSimSerialNumber();
    if (iccid == null || iccid.length() < 20) {
        SubscriptionManager sm = SubscriptionManager.from(context);
        List<SubscriptionInfo> sis = sm.getActiveSubscriptionInfoList();
        if (sis.size() >= 1) {
            SubscriptionInfo si1 = sis.get(0); // 卡一
            iccid = si1.getIccId();
        }
    }
    return iccid;
 }
2.系统对应用的权限检查
  • 源码路径:frameworks/base/telephony/java/android/telephony/TelephonyManager.java
 @SuppressAutoDoc // No support for device / profile owner or carrier privileges (b/72967236).
 @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE)
 public String getSimSerialNumber() {
      return getSimSerialNumber(getSubId());
 }

 @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE)
 @UnsupportedAppUsage
 public String getSimSerialNumber(int subId) {
     try {
         IPhoneSubInfo info = getSubscriberInfoService();
         if (info == null)
             return null;
         return info.getIccSerialNumberForSubscriber(subId, mContext.getOpPackageName(),
                 mContext.getAttributionTag());
     } catch (RemoteException ex) {
         return null;
     } catch (NullPointerException ex) {
         // This could happen before phone restarts due to crashing
         return null;
     }
 }

可以看到getSimSerialNumber()方法要求声明android.permission.READ_PRIVILEGED_PHONE_STATE权限
然后调用IPhoneSubInfo的getIccSerialNumberForSubscriber()方法

  • 源码路径:frameworks/opt/telephony/src/java/com/android/internal/telephony/PhoneSubInfoController.java
 public class PhoneSubInfoController extends IPhoneSubInfo.Stub {
 	省略部分代码。。。
 	
 	public String getIccSerialNumberForSubscriber(int subId, String callingPackage,
            String callingFeatureId) {
    	return callPhoneMethodForSubIdWithReadSubscriberIdentifiersCheck(subId, callingPackage,
                callingFeatureId, "getIccSerialNumber", (phone) -> phone.getIccSerialNumber());
    }
    
    省略部分代码。。。
    
 	private <T> T callPhoneMethodForSubIdWithReadSubscriberIdentifiersCheck(int subId,
            String callingPackage, @Nullable String callingFeatureId, String message,
            CallPhoneMethodHelper<T> callMethodHelper) {
        // 调用Phone的相关方法,进行权限检查
        return callPhoneMethodWithPermissionCheck(subId, callingPackage, callingFeatureId,
                message, callMethodHelper,
                (aContext, aSubId, aCallingPackage, aCallingFeatureId, aMessage)->
                        TelephonyPermissions.checkCallingOrSelfReadSubscriberIdentifiers(
                                aContext, aSubId, aCallingPackage, aCallingFeatureId, aMessage));
    }
 }

在TelephonyPermissions.checkCallingOrSelfReadSubscriberIdentifiers方法中判断是否有权限获取ICCID

  • 源码路径:frameworks/base/telephony/common/com/android/internal/telephony/TelephonyPermissions.java
 public static boolean checkCallingOrSelfReadSubscriberIdentifiers(Context context, int subId,
         String callingPackage, @Nullable String callingFeatureId, String message) {
     return checkPrivilegedReadPermissionOrCarrierPrivilegePermission(
              context, subId, callingPackage, callingFeatureId, message, false);
 }
 
 private static boolean checkPrivilegedReadPermissionOrCarrierPrivilegePermission(
         Context context, int subId, String callingPackage, @Nullable String callingFeatureId,
         String message, boolean allowCarrierPrivilegeOnAnySub) {
     int uid = Binder.getCallingUid();
     int pid = Binder.getCallingPid();
     
     // 调用包是否具有运营商特权
     // If the calling package has carrier privileges for specified sub, then allow access.
     if (checkCarrierPrivilegeForSubId(context, subId)) return true;

     // If the calling package has carrier privileges for any subscription
     // and allowCarrierPrivilegeOnAnySub is set true, then allow access.
     if (allowCarrierPrivilegeOnAnySub && checkCarrierPrivilegeForAnySubId(context, uid)) {
         return true;
     }
        
     PermissionManager permissionManager = (PermissionManager) context.getSystemService(
             Context.PERMISSION_SERVICE);
     // 检查是否通过设备标识授权
     if (permissionManager.checkDeviceIdentifierAccess(callingPackage, message, callingFeatureId,
             pid, uid) == PackageManager.PERMISSION_GRANTED) {
         return true;
     }

     return reportAccessDeniedToReadIdentifiers(context, subId, pid, uid, callingPackage,
             message);
 }
 
 //当具有给定pid/uid的应用程序无法访问所请求的标识符时,报告失败
 private static boolean reportAccessDeniedToReadIdentifiers(Context context, int subId, int pid,
         int uid, String callingPackage, String message) {
     ApplicationInfo callingPackageInfo = null;
     
     省略部分代码。。。
     
     Log.w(LOG_TAG, "reportAccessDeniedToReadIdentifiers:" + callingPackage + ":" + message + ":"
             + subId);
     // if the target SDK is pre-Q then check if the calling package would have previously
     // had access to device identifiers.
     if (callingPackageInfo != null && (
             callingPackageInfo.targetSdkVersion < Build.VERSION_CODES.Q)) {
         if (context.checkPermission(
                 android.Manifest.permission.READ_PHONE_STATE,
                 pid,
                 uid) == PackageManager.PERMISSION_GRANTED) {
             return false;
         }
         if (checkCarrierPrivilegeForSubId(context, subId)) {
             return false;
         }
     }
     throw new SecurityException(message + ": The user " + uid
             + " does not meet the requirements to access device identifiers.");
 }    

从上面代码可以看到,如果发起调用的应用信息不为空并且targetSdkVersion值小于29,且READ_PHONE_STATE权限已授予,就返回false。此时应用获取的iccid值为null不会报错;如果不满足这些条件直接抛出SecurityException异常。

所以在checkPrivilegedReadPermissionOrCarrierPrivilegePermission中直接根据包名授权。文章来源地址https://www.toymoban.com/news/detail-437799.html

 private static boolean checkPrivilegedReadPermissionOrCarrierPrivilegePermission(
         Context context, int subId, String callingPackage, @Nullable String callingFeatureId,
         String message, boolean allowCarrierPrivilegeOnAnySub) {
     int uid = Binder.getCallingUid();
     int pid = Binder.getCallingPid();
     
     // If the calling package has carrier privileges for specified sub, then allow access.
     if (checkCarrierPrivilegeForSubId(context, subId)) return true;

     // If the calling package has carrier privileges for any subscription
     // and allowCarrierPrivilegeOnAnySub is set true, then allow access.
     if (allowCarrierPrivilegeOnAnySub && checkCarrierPrivilegeForAnySubId(context, uid)) {
         return true;
     }
        
     PermissionManager permissionManager = (PermissionManager) context.getSystemService(
             Context.PERMISSION_SERVICE);
     if (permissionManager.checkDeviceIdentifierAccess(callingPackage, message, callingFeatureId,
             pid, uid) == PackageManager.PERMISSION_GRANTED) {
         return true;
     }
     
     // add start for skip permission check
     if (callingPackage != null && callingPackage.equals("com.xxx.xxx")) {
         Log.d(LOG_TAG, "com.xxx.xxx skip permission check of "+message);
         return true;
     }
     // add end

     return reportAccessDeniedToReadIdentifiers(context, subId, pid, uid, callingPackage,
             message);
 }

到了这里,关于Android11 授权应用获取IMEI号和ICCID的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • Android 11 获取启动其他应用

    本文代码地址 https://gitee.com/chenjim/QueryAppInfo 最新更新地址 https://gitee.com/chenjim/chenjimblog 如果应用以 Android 11(API 级别 30)或更高版本为目标平台,并查询与设备上已安装的其他应用相关的信息,则系统在默认情况下会过滤此信息。 此过滤行为意味着您的应用无法检测设备上

    2024年02月14日
    浏览(32)
  • Android读取SIM卡ICCID

    方法一,使用TelephonyManager的getSimSerialNumber()获取 需要添加权限:uses-permission android:name=\\\"android.permission.READ_PHONE_STATE\\\" / 方法二,通过发AT命令读取SIM卡ICCID(可以解决读取某些SIM卡ICCID长度不对的问题)

    2024年02月16日
    浏览(48)
  • 解决uniapp手机端获取用户设备是否授权,进行授权提示,获取用户相机授权(Android 权限清单整理)

    最近在上架app时遇到了一些授权询问的问题,在这里简单记录一下,主要使用的是uniapp进行开发,在官网中有说明使用uni.authorize()进行授权请求,但是该方法不支持h5和app,所以采用plus.android.requestPermissions()方法进行授权判断操作,话不多说直接上代码 以下代码进行的

    2024年02月05日
    浏览(53)
  • 公众号和小程序获取用户信息及获取手机号

    公众号的获取用户信息 前端传code,后端根据code获取用户信息 代码: 小程序获取用户信息 前端传iv,encryptedData,code,然后后端根据code获取session_key,再利用session_key,encryptedData及iv来获取用户信息 注意:前端wx.login获取code和获取用户信息的顺序 代码:(用的easyWeChat) 小程

    2024年02月11日
    浏览(53)
  • 获取 github 仓库最新版本号和版本号列表的 API

    github 仓库,获取指定项目的最新版本号和所有版本号列表的两个API如下: 获取最新发布的一个的版本信息 以 fatedier/frp 项目为例,对应的 API 地址为 https://api.github.com/repos/fatedier/frp/releases/latest 所有版本信息 以 fatedier/frp 项目为例,对应的 API 地址为 https://api.github.com/repos/f

    2024年02月13日
    浏览(61)
  • 微信公众号和微信小程序进程名获取及配置

    微信公众号和微信小程序使用到了webview,但是和混合应用有区别。微信公众号和微信小程序不是利用安卓默认的浏览器内核,做了二次开发,称为X5内核。 1、开启X5内核调试模式 这个操作必须在真机上进行,模拟器无法操作 1.1 微信版本在7.0以下(不包含7.0),可以在任意聊

    2024年02月10日
    浏览(47)
  • Linux C/C++ 获取进程号、线程号和设置线程名

    在Linux开发过程中,设计多线程开发时可以将进程和线程的 id 打印出来,方便开发调试和后期查问题使用,同时也包括设置线程名。 Linux中,每个进程有一个pid,类型pid_t,由 getpid() 取得。Linux下的POSIX线程也有一个id,类型 pthread_t,由pthread_self()取得,该id由线程库维护,其

    2024年02月11日
    浏览(35)
  • Android 12.0根据包名授予读取IMEI权限

     在12.0的产品开发中,对于读取设备的imei sn号功能也是常有的,而在10.0以后对于读取imei也是受权限要求越来越多了一般的app是读取不到这个权限了,根据产品需求需要读取这个权限,所以需要在系统中对这个app授权让它读取包名,从而实现功能  首选在app中看如何获取ime

    2024年02月06日
    浏览(61)
  • uniapp 企业微信侧边栏开发网页授权 注入企业权限 注入应用权限 获取userid(2)

    想知道怎么搭建一个企业微信侧边栏应用的,请移步: https://blog.csdn.net/u013361179/article/details/131936040?spm=1001.2014.3001.5501 1、网页授权,获取code 代码: 里面用到的方法: // 获取url后参数code // 删除URL中指定search参数 这个时候就会发现,如果你是从企业微信客户端侧边栏配置的

    2024年02月12日
    浏览(41)
  • 【Android 11/12】 通过Uri获取绝对路径的方法

    原理:通过对不同的Uri进行辨别,提取ID, 需要 android.permission.MANAGE_EXTERNAL_STORAGE 权限 直接获取\\\"primary:\\\"后的路径即可,后面即是相对路径. 与下一个类似,获取ID后进入数据表中查找. 进入MediaStore.Files表中进行查询_data字段,旧版通过直接查询uri的方法获取_data已经无效. 下面

    2024年02月15日
    浏览(44)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包