You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在Android 10/11/12中代码获取IMEI?解决SecurityException问题

嘿,我来帮你梳理下在Android 10、11、12里获取IMEI的正确姿势,还有你遇到的那个java.lang.SecurityException的解决办法——本质都是Google从Android 10开始逐步收紧设备标识符访问权限导致的,咱们一步步说:

Android 10 (API 29) & Android 11 (API 30) 的IMEI获取规则

从Android 10开始,Google就把IMEI这类敏感设备标识符的访问权限锁得很死了:

  • 普通第三方应用完全拿不到IMEI:哪怕你申请了READ_PHONE_STATE权限也没用,这个权限现在只能用来获取一些非敏感的电话状态信息,比如通话状态。
  • 只有少数特殊应用能获取:
    • 带系统签名的系统应用
    • 设备所有者(Device Owner)或配置文件所有者(Profile Owner)应用(比如企业管理类APP)
    • 运营商官方的应用(需要运营商授予的特殊权限)
  • 如果你的应用属于上述特殊范畴,代码可以这么写:
TelephonyManager telephonyManager = (TelephonyManager) getSystemService(Context.TELEPHONY_SERVICE);
if (checkSelfPermission(Manifest.permission.READ_PRIVILEGED_PHONE_STATE) == PackageManager.PERMISSION_GRANTED) {
    String imei = telephonyManager.getImei();
    // 后续处理IMEI逻辑
}

注意:READ_PRIVILEGED_PHONE_STATE是系统级权限,普通APP在Google Play上根本申请不到,只能通过厂商签名或者设备所有者模式才能拿到。

Android 12 (API 31) 的权限收紧与报错解决

你碰到的getSerial: The user 10034 does not meet the requirements to access device identifiers报错,是因为Android 12把权限限制又提了一个等级:

  • 哪怕你拿到了READ_PRIVILEGED_PHONE_STATE权限,也得满足以下条件之一才能调用getImei()、getSerial()这类方法:
    1. 应用是系统应用
    2. 应用是设备所有者/配置文件所有者
    3. 应用拥有ACCESS_FINE_LOCATION权限,且是专门的通话类应用(比如拨号器、通话记录APP)——这个限制也非常严格,普通APP基本碰不到
    4. 应用是运营商授权的官方应用

对普通第三方应用的解决方案

如果你的APP是普通的第三方应用,别再纠结IMEI了——Google的隐私政策就是不让你拿,硬要碰只会报错。推荐用这些替代方案:

  • 广告ID(Advertising ID):适合广告追踪、用户识别场景,不需要特殊权限,代码示例:
try {
    AdvertisingIdClient.Info adInfo = AdvertisingIdClient.getAdvertisingIdInfo(getApplicationContext());
    String advertisingId = adInfo.getId();
    boolean isLimitAdTracking = adInfo.isLimitAdTrackingEnabled();
    // 广告ID逻辑处理
} catch (IOException | GooglePlayServicesNotAvailableException | GooglePlayServicesRepairableException e) {
    e.printStackTrace();
}

注意:需要依赖Google Play Services,而且用户可以随时重置或关闭广告ID,所以不能用来做永久唯一标识。

  • 自定义唯一标识符:自己生成一个UUID,存在SharedPreferences或者本地文件里,应用卸载后会消失,但足够满足大多数普通APP的用户识别需求:
SharedPreferences prefs = getSharedPreferences("MyAppPrefs", Context.MODE_PRIVATE);
String uniqueDeviceId = prefs.getString("UniqueDeviceId", null);

if (uniqueDeviceId == null) {
    uniqueDeviceId = UUID.randomUUID().toString();
    prefs.edit().putString("UniqueDeviceId", uniqueDeviceId).apply();
}
// 用这个uniqueDeviceId来做用户识别
  • Android ID:这是设备首次启动时生成的64位字符串,除非恢复出厂设置否则不会变。不过要注意,Android 8.0及以上,每个APP拿到的Android ID都是独立的,不同APP之间不共享:
String androidId = Settings.Secure.getString(getContentResolver(), Settings.Secure.ANDROID_ID);

总结一下

Android 10及以上,普通第三方APP获取IMEI的路基本被堵死了——这是Google为了保护用户隐私制定的规则,没办法绕开。如果你的应用不是系统/运营商/设备所有者类APP,老老实实用替代方案才是正途,既符合规范,也能满足业务需求。

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.04 16:45:29