Android 10设备所有者应用调用getDeviceID()获取IMEI失败咨询
为什么设了设备所有者还是拿不到IMEI?
我来帮你拆解这个问题——我之前也帮不少企业用户处理过类似的设备追踪需求,你的情况其实是Android 10+权限体系收紧后的典型问题,核心原因有两个:
- Android 10+的标识符权限彻底收紧:谷歌从API 29开始,把IMEI、MEID这类电话标识符的访问权限锁得非常死。哪怕你是设备所有者,只要你的应用不是系统级应用或者没有拿到
READ_PRIVILEGED_PHONE_STATE这个特权权限,调用getDeviceId()就会抛出SecurityException。设备所有者权限主要管的是设备管理能力(比如强制安装应用、锁屏、限制系统设置),和访问敏感硬件标识符的权限是完全分开的两个体系,不能混为一谈。 - 你的应用身份还是普通第三方应用:通过
adb shell dpm set-device-owner com.package.name/.MyDeviceAdminReceiver设置的设备所有者,本质上还是一个普通的第三方应用(除非你把它放到系统目录并签名),并没有自动获得READ_PRIVILEGED_PHONE_STATE权限——这个权限只有系统预装的应用或者和厂商有合作的应用才能拿到,普通用户通过adb是无法直接赋予的。
可行的IMEI/设备标识符获取方案
根据你的批量设备管理需求,给你三个实用方案:
方案1:用设备序列号替代IMEI(推荐)
Android 10+明确允许设备所有者应用通过Build.getSerial()获取设备序列号,这个标识符也是唯一的,完全可以满足设备追踪的需求,而且不需要任何额外权限。调用代码很简单:String serialNumber = Build.getSerial();补充:如果你的设备包含Android 8.0以下的版本,
Build.getSerial()可能需要READ_PHONE_STATE权限,但你针对的是Android 10+设备,所以直接用就行。方案2:将应用转为系统级应用(仅当必须要IMEI时)
如果你的业务逻辑必须依赖IMEI,那只能把应用变成系统应用,步骤如下:- 获取设备的Root权限,或者联系设备厂商将你的应用预装到
/system/priv-app目录下; - 用设备厂商的系统签名对APK进行签名;
- 在AndroidManifest.xml中声明特权权限:
<uses-permission android:name="android.permission.READ_PRIVILEGED_PHONE_STATE" />
这样处理后,你的应用作为系统级设备所有者,就能正常调用
getDeviceId()获取IMEI了。不过这个方案门槛较高,需要Root或者厂商配合。- 获取设备的Root权限,或者联系设备厂商将你的应用预装到
方案3:利用EMM平台的API(适合大规模设备管理)
如果你是管理大量企业设备,更推荐使用官方的EMM(企业移动管理)框架。EMM平台可以通过设备管理API直接获取IMEI,不需要你的应用自己调用敏感接口。这种方式更适合批量设备的统一管理,而且符合谷歌的权限规范。
内容的提问来源于stack exchange,提问作者odgatelmand




