You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

Android 9系统级应用无法获取IMEI,配置权限仍触发安全异常

嘿,这个问题我太熟悉了!Android 9(API 28)对设备敏感标识符的权限管控做了大幅收紧,哪怕是系统级应用,只加READ_PHONE_STATE也拿不到IMEI,给你拆解下原因和可行的解决办法:

为什么会报SecurityException?

Android 9开始,Google直接限制了普通READ_PHONE_STATE权限对IMEI(getImei())的访问权限——哪怕是系统应用也不行。想要获取这类核心设备标识符,必须使用系统级专属权限,同时满足系统签名等条件。

解决步骤

1. 替换Manifest中的权限

把原来的READ_PHONE_STATE替换成系统级的特权权限:

<uses-permission android:name="android.permission.READ_PRIVILEGED_PHONE_STATE" />

这个权限只有系统签名的应用才能申请通过,普通应用根本用不了,刚好符合你的系统级应用场景。

2. 确保你的应用是真正的系统级应用

光加权限还不够,得保证应用满足系统应用的核心条件:

  • 在Manifest里添加android:sharedUserId="android.uid.system",让应用运行在系统进程空间
  • 用和当前ROM一致的系统签名打包APK
  • 将APK放到设备的/system/app/system/priv-app目录下(不同厂商ROM可能有细微差异,优先放priv-app

3. 代码层面的安全适配

调用getImei()时记得加版本判断和异常捕获,避免崩溃:

public String getDeviceImei(Context context) {
    TelephonyManager telephonyManager = (TelephonyManager) context.getSystemService(Context.TELEPHONY_SERVICE);
    String imei = null;
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
        try {
            imei = telephonyManager.getImei();
        } catch (SecurityException e) {
            Log.e("IMEI_ERROR", "获取IMEI失败:" + e.getMessage());
            // 这里可以加备选逻辑,比如用Android ID替代
        }
    } else {
        // 适配低版本,你当前是Android 9,这段主要兼容旧系统
        try {
            imei = telephonyManager.getDeviceId();
        } catch (SecurityException e) {
            Log.e("IMEI_ERROR", "获取设备ID失败:" + e.getMessage());
        }
    }
    return imei;
}

4. 备选方案:实在拿不到IMEI怎么办?

如果因为ROM定制等原因还是无法获取IMEI,可以考虑用其他标识符替代:

  • Android ID:通过Settings.Secure.getString(context.getContentResolver(), Settings.Secure.ANDROID_ID)获取,需要READ_SETTINGS权限,系统应用可正常访问,但恢复出厂设置会变更
  • 自定义UUID:第一次启动APP时生成一个UUID,存在SharedPreferences或本地文件中,之后复用,稳定性高但无法和硬件绑定

内容的提问来源于stack exchange,提问作者xubilulive

火山引擎 最新活动