java.lang.SecurityException: getImeiForSlot: The user 10282 does not meet the requirement

项目场景:

这两天项目升级Android 编译版本,将build.gradle 中的 compileSdkVersion 升级到 29后,发现APP在Android 10 及Android 11设备上在调用获取设备信息的时候崩溃了。


问题描述:

Android 编译版本升级为29后,在Android 10 和Android 11 手机上获取设备信息崩溃,报错
java.lang.SecurityException: getImeiForSlot: The user 10282 does not meet the requirements to access device identifiers.
在这里插入图片描述

Caused by: java.lang.SecurityException: getImeiForSlot: The user 10282 does not meet the requirements to access device identifiers.
        at android.os.Parcel.createExceptionOrNull(Parcel.java:2376)
        at android.os.Parcel.createException(Parcel.java:2360)
        at android.os.Parcel.readException(Parcel.java:2343)
        at android.os.Parcel.readException(Parcel.java:2285)
        at com.android.internal.telephony.ITelephony$Stub$Proxy.getImeiForSlot(ITelephony.java:11511)
        at android.telephony.TelephonyManager.getImei(TelephonyManager.java:2060)
        at android.telephony.TelephonyManager.getImei(TelephonyManager.java:2015)
        at com.bthvi.myapplication.PhoneStateHelper.getDeviceId(PhoneStateHelper.kt:82)

原因分析:

首先,贴下我的代码:

 val telephonyManager = context.getSystemService(Activity.TELEPHONY_SERVICE) as TelephonyManager
     if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
          telephonyManager.imei
     } else {
          telephonyManager.deviceId
     }

这里崩溃是发生在获取 IMEI ,其实获取 deviceId 也是会崩溃的。

通过查看 Google Android开发者官方文档《唯一标识符最佳做法》发现
自 Android 10(API 级别 29)起,您的应用必须是设备或个人资料所有者应用,具有特殊运营商许可,或具有 READ_PRIVILEGED_PHONE_STATE 特权,才能访问不可重置的设备标识符。
在这里插入图片描述


解决方案:

1、降低targetSdkVersion版本

我们可以将支持版本降低到 29 一下,也就是 targetSdkVersion=28 这样就可以解决问题了。但是这种做法不建议,毕竟后面还是要升级到新版本的。

2、使用官方推荐方法

也就是我们前面在文档中看到的,使用SSAID,实例ID、广告ID,随机生成的ID等。具体可以看下文档,这里贴出我的改造方案。

if (context.applicationInfo.targetSdkVersion >= 29 && Build.VERSION.SDK_INT >= 29 ){
		//大于等于29使用特殊方法
      getUniqueID(context);
 }
  private fun getUniqueID(context: Context): String? {
    var id: String? = null
    val androidId = Settings.Secure.getString(context.contentResolver, Settings.Secure.ANDROID_ID)
    if (!Tool.isEmpty(androidId) && "9774d56d682e549c" != androidId) {
      try {
        val uuid = UUID.nameUUIDFromBytes(androidId.toByteArray(charset("utf8")))
        id = uuid.toString()
      } catch (e: Exception) {
        e.printStackTrace()
      }
    }
    if (Tool.isEmpty(id)) {
      id = getUUID()
    }
    return if (Tool.isEmpty(id)) UUID.randomUUID().toString() else id
  }
  private fun getUUID(): String? {
    var serial: String? = null
    val m_szDevIDShort = "35" + Build.BOARD.length % 10 + Build.BRAND.length % 10 + (if (null != Build.CPU_ABI) Build.CPU_ABI.length else 0) % 10 + Build.DEVICE.length % 10 + Build.DISPLAY.length % 10 + Build.HOST.length % 10 + Build.ID.length % 10 + Build.MANUFACTURER.length % 10 + Build.MODEL.length % 10 + Build.PRODUCT.length % 10 + Build.TAGS.length % 10 + Build.TYPE.length % 10 + Build.USER.length % 10 //13 位
    if (Build.VERSION.SDK_INT <= 29) {
      try {
        serial = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
          Build.getSerial()
        } else {
          Build.SERIAL
        }
        //API>=9 使用serial号
        return UUID(m_szDevIDShort.hashCode().toLong(), serial.hashCode().toLong()).toString()
      } catch (exception: java.lang.Exception) {
        serial = "serial" // 随便一个初始化
      }
    } else {
      serial = Build.UNKNOWN // 随便一个初始化
    }

    //使用硬件信息拼凑出来的15位号码
    return UUID(m_szDevIDShort.hashCode().toLong(), serial.hashCode().toLong()).toString()
  }
  • 7
    点赞
  • 17
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 3
    评论
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

紫雾凌寒

你的鼓励是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值