Android 10 使用getDeviceId()和getIMEI()的问题及方案

在Android 10上,应用升级targetSDKVersion到API 29后,调用getDeviceId()和getIMEI()会导致崩溃,因为需要READ_PRIVILEGED_PHONE_STATE权限。第三方应用无法从Google Play声明此权限。解决方案包括使用Android广告ID替代,或者对于设备所有者或资料所有者应用,使用普通PHONE权限。
摘要由CSDN通过智能技术生成

问题背景:

应用升级了targetSDKVersion 到api 29,也就是Android 10,之前一些应用内用到getDeviceIdgetIMEI就出了问题,但是调用这些api的时候,都进行了try catch,但是在小米9手机上还是会崩溃:

AndroidRuntime: FATAL EXCEPTION: Thread-4326
E AndroidRuntime: Process: xxx, PID: 13895
E AndroidRuntime:java.lang.SecurityException: getDeviceId: The user 10222 does not meet the requirements to access device identifiers.
E AndroidRuntime: at android.os.Parcel.createException(Parcel.java:2074)
E AndroidRuntime: at android.os.Parcel.readException(Parcel.java:2042)
E AndroidRuntime: at android.os.Parcel.readException(Parcel.java:1990)
E AndroidRuntime: at com.android.internal.telephony.ITelephonyStubProxy.getDeviceId(ITelephony.java:10389)
E AndroidRuntime: at android.telephony.TelephonyManager.getDeviceId(TelephonyManager.java:1629)

我猜测和小米的room有关,在这先不进一步讨论了

问题原因

从 Android 10 开始,应用必须具有 READ_PRIVILEGED_PHONE_STATE 特许权限才能访问设备的不可重置标识符(包含 IMEI 和序列号)。

注意:从 Google Play 商店安装的第三方应用无法声明特许权限。

受影响的方法包括:

如果您的应用没有该权限,但您仍尝试查询不可重置标识符的相关信息,则平台的响应会因目标 SDK 版本而异:

  • 如果应用以 Android 10 或更高版本为目标平台,则会发生 SecurityException
  • 如果应用以 Android 9(API 级别 28)或更低版本为目标平台,则相应方法会返回 null 或占位符数据(如果应用具有 READ_PHONE_STATE 权限)。否则,会发生 SecurityException

注意:如果您的应用是设备所有者或资料所有者应用,那么即使您的应用以 Android 10 或更高版本为目标平台,您也只需 READ_PHONE_STATE 权限即可访问不可重置的设备标识符。此外,如果您的应用具有特殊运营商权限,则无需任何权限即可访问这些标识符。

许多使用场景都不需要不可重置的设备标识符。例如,如果您的应用将不可重置的设备标识符用于广告跟踪或用户分析目的,请为这些特定使用场景使用 Android 广告 ID。要了解详情,请参阅唯一标识符的最佳做法

具体可以参考这篇文章:android 10 的隐私权和位置信息

解决方案

代码:

public static String getIMEIDeviceId(Context context) {
<span class="token class-name">String</span> deviceId<span class="token punctuation">;</span>

<span class="token keyword">if</span> <span class="token punctuation">(</span><span class="token class-name">Build</span><span class="token punctuation">.</span>VERSION<span class="token punctuation">.</span>SDK_INT <span class="token operator">&gt;=</span> <span class="token class-name">Build</span><span class="token punctuation">.</span>VERSION_CODES<span class="token punctuation">.</span><span class="token class-name">Q</span><span class="token punctuation">)</span>
<span class="token punctuation">{</span>
    deviceId <span class="token operator">=</span> <span class="token class-name">Settings</span><span class="token punctuation">.</span><span class="token class-name">Secure</span><span class="token punctuation">.</span><span class="token function">getString</span><span class="token punctuation">(</span>context<span class="token punctuation">.</span><span class="token function">getContentResolver</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">,</span> <span class="token class-name">Settings</span><span class="token punctuation">.</span><span class="token class-name">Secure</span><span class="token punctuation">.</span>ANDROID_ID<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span> <span class="token keyword">else</span> <span class="token punctuation">{</span>
    <span class="token keyword">final</span> <span class="token class-name">TelephonyManager</span> mTelephony <span class="token operator">=</span> <span class="token punctuation">(</span><span class="token class-name">TelephonyManager</span><span class="token punctuation">)</span> context<span class="token punctuation">.</span><span class="token function">getSystemService</span><span class="token punctuation">(</span><span class="token class-name">Context</span><span class="token punctuation">.</span>TELEPHONY_SERVICE<span class="token punctuation">)</span><span class="token punctuation">;</span>
    <span class="token keyword">if</span> <span class="token punctuation">(</span><span class="token class-name">Build</span><span class="token punctuation">.</span>VERSION<span class="token punctuation">.</span>SDK_INT <span class="token operator">&gt;=</span> <span class="token class-name">Build</span><span class="token punctuation">.</span>VERSION_CODES<span class="token punctuation">.</span><span class="token class-name">M</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
        <span class="token keyword">if</span> <span class="token punctuation">(</span>context<span class="token punctuation">.</span><span class="token function">checkSelfPermission</span><span class="token punctuation">(</span><span class="token class-name">Manifest</span><span class="token punctuation">.</span>permission<span class="token punctuation">.</span>READ_PHONE_STATE<span class="token punctuation">)</span> <span class="token operator">!=</span> <span class="token class-name">PackageManager</span><span class="token punctuation">.</span>PERMISSION_GRANTED<span class="token punctuation">)</span> <span class="token punctuation">{</span>
            <span class="token keyword">return</span> <span class="token string">""</span><span class="token punctuation">;</span>
        <span class="token punctuation">}</span>
    <span class="token punctuation">}</span>
    <span class="token keyword">assert</span> mTelephony <span class="token operator">!=</span> <span class="token keyword">null</span><span class="token punctuation">;</span>
    <span class="token keyword">if</span> <span class="token punctuation">(</span>mTelephony<span class="token punctuation">.</span><span class="token function">getDeviceId</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token operator">!=</span> <span class="token keyword">null</span><span class="token punctuation">)</span>
    <span class="token punctuation">{</span>
        <span class="token keyword">if</span> <span class="token punctuation">(</span><span class="token class-name">Build</span><span class="token punctuation">.</span>VERSION<span class="token punctuation">.</span>SDK_INT <span class="token operator">&gt;=</span> <span class="token class-name">Build</span><span class="token punctuation">.</span>VERSION_CODES<span class="token punctuation">.</span><span class="token class-name">O</span><span class="token punctuation">)</span>
        <span class="token punctuation">{</span>
            deviceId <span class="token operator">=</span> mTelephony<span class="token punctuation">.</span><span class="token function">getImei</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
        <span class="token punctuation">}</span><span class="token keyword">else</span> <span class="token punctuation">{</span>
            deviceId <span class="token operator">=</span> mTelephony<span class="token punctuation">.</span><span class="token function">getDeviceId</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
        <span class="token punctuation">}</span>
    <span class="token punctuation">}</span> <span class="token keyword">else</span> <span class="token punctuation">{</span>
        deviceId <span class="token operator">=</span> <span class="token class-name">Settings</span><span class="token punctuation">.</span><span class="token class-name">Secure</span><span class="token punctuation">.</span><span class="token function">getString</span><span class="token punctuation">(</span>context<span class="token punctuation">.</span><span class="token function">getContentResolver</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">,</span> <span class="token class-name">Settings</span><span class="token punctuation">.</span><span class="token class-name">Secure</span><span class="token punctuation">.</span>ANDROID_ID<span class="token punctuation">)</span><span class="token punctuation">;</span>
    <span class="token punctuation">}</span>
<span class="token punctuation">}</span>
<span class="token class-name">Log</span><span class="token punctuation">.</span><span class="token function">d</span><span class="token punctuation">(</span><span class="token string">"deviceId"</span><span class="token punctuation">,</span> deviceId<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token keyword">return</span> deviceId<span class="token punctuation">;</span>

}

参考链接:
1.https://stackoverflow.com/questions/55173823/i-am-getting-imei-null-in-android-q
2.https://source.android.com/devices/tech/config/uicc

有些文章是从developer cp而来,怕一些同学没有梯子看不到,所以就直接粘贴了

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值