目录
概述IMEI详解什么是IMEI特点权限要求获取方式
ANDROID_ID详解什么是ANDROID_ID特点获取方式Android 8.0重要变更说明
OAID详解什么是OAID特点支持的厂商获取方式厂商特定获取方式(华为示例)
获取失败的情况IMEI获取失败的原因ANDROID_ID获取失败的原因OAID获取失败的原因
业务场景选择适合使用IMEI的场景适合使用ANDROID_ID的场景适合使用OAID的场景对比表
常见问题解答Q1: 为什么有时候获取不到设备ID?Q2: IMEI、ANDROID_ID和OAID哪个更好?Q3: 卸载重装应用后,ANDROID_ID会改变吗?Q4: OAID卸载重装会变吗?Q5: 如何确保设备标识的稳定性?Q6: 在接口传参中应该使用哪个?Q7: OAID需要Android 10以上才能获取吗?
总结
概述
在Android开发中,设备标识符是重要的技术概念,主要用于用户识别、设备绑定、数据统计等场景。本文档详细对比了IMEI、ANDROID_ID和OAID三种主要的设备标识符,帮助非技术人员理解其差异和使用场景 (ps:经常有各个职能的同事来向我咨询这些标识符的意义作用、唯一性、稳定性、区别、是否存在可能拿不到的情况,以及什么情况下会拿不到标识符等问题。因此,我觉得系统整理一下还是很有意义的)。
IMEI详解
什么是IMEI
IMEI(International Mobile Equipment Identity)是国际移动设备识别码,是手机的唯一硬件标识符。
特点
设备级别唯一:每台设备都有唯一的IMEI硬件级别持久:不会因应用卸载重装而改变需要权限:需要READ_PHONE_STATE权限版本限制:Android 10+普通应用无法获取
权限要求
获取方式
// 需要动态申请权限(Android 6.0+)
TelephonyManager tm = (TelephonyManager) context.getSystemService(Context.TELEPHONY_SERVICE);
String imei = tm.getDeviceId(); // Android 10以下
String imei = tm.getImei(); // Android 10+
ANDROID_ID详解
什么是ANDROID_ID
ANDROID_ID是Android系统为每个应用生成的唯一标识符,由系统自动管理。
特点
应用级别唯一:每个应用都有独立的ANDROID_ID无需权限:不需要任何权限即可获取隐私友好:不会泄露用户个人信息Android版本差异:
Android 8.0以下:卸载重装后会改变Android 8.0及以上:基于应用签名生成,相同签名的应用卸载重装后不会改变
获取方式
// 无需权限,直接获取
String androidId = Settings.Secure.getString(context.getContentResolver(), Settings.Secure.ANDROID_ID);
Android 8.0重要变更说明
Android 8.0 (API 26) 对ANDROID_ID的重大改变:
在Android 8.0之前,ANDROID_ID是设备级别的,所有应用获取到的值都相同,卸载重装后会改变。
从Android 8.0开始,ANDROID_ID的生成规则变为:
// Android 8.0+ ANDROID_ID生成规则(伪代码)
ANDROID_ID = hash(应用签名密钥 + 用户ID + 设备唯一标识)
这意味着:
不同应用:即使在同一设备上,不同签名的应用获取到不同的ANDROID_ID相同应用:相同签名的应用,在同一用户下,获取到相同的ANDROID_ID卸载重装:使用相同签名的应用重装后,ANDROID_ID保持不变多用户:同一应用在不同用户下,获取到不同的ANDROID_ID
验证代码:
/**
* 验证ANDROID_ID的Android 8.0行为变更
*/
public static void verifyAndroidIdBehavior(Context context) {
String androidId = Settings.Secure.getString(context.getContentResolver(), Settings.Secure.ANDROID_ID);
Log.d("AndroidId", "当前ANDROID_ID: " + androidId);
Log.d("AndroidId", "Android版本: " + Build.VERSION.SDK_INT);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
Log.i("AndroidId", "Android 8.0+: ANDROID_ID基于应用签名生成,卸载重装后不变");
} else {
Log.i("AndroidId", "Android 8.0以下: ANDROID_ID设备级别,卸载重装后会改变");
}
// 获取应用签名信息
try {
PackageInfo packageInfo = context.getPackageManager()
.getPackageInfo(context.getPackageName(), PackageManager.GET_SIGNATURES);
String signature = packageInfo.signatures[0].toCharsString();
Log.d("AndroidId", "应用签名: " + signature.substring(0, 16) + "...");
} catch (Exception e) {
Log.e("AndroidId", "获取应用签名失败", e);
}
}
OAID详解
什么是OAID
OAID(Open Anonymous Device Identifier)是中国移动安全联盟(MSA)推出的开放匿名设备标识符,旨在替代IMEI等传统设备标识符。
特点
设备级别唯一:与设备绑定,卸载重装应用后保持不变无需权限:不需要特殊权限即可获取隐私友好:用户可在系统设置中重置厂商支持:主要支持国内主流厂商设备版本兼容:不依赖Android系统版本,主要看厂商实现
支持的厂商
华为:EMUI 9.0/10.0及以上小米:MIUI 10及以上OPPO:ColorOS 6.0及以上vivo:FuntouchOS 9.0及以上三星:OneUI 2.0及以上魅族:Flyme 7.0及以上
获取方式
// 使用MSA SDK获取OAID
MdidSdkHelper.InitSdk(context, true, new IIdentifierListener() {
@Override
public void OnSupport(boolean support, IdSupplier extra) {
if (support) {
String oaid = extra.oaid; // 获取到的OAID
}
}
});
厂商特定获取方式(华为示例)
// 华为HMS Core方式获取OAID
AdvertisingIdClient.Info adInfo = AdvertisingIdClient.getAdvertisingIdInfo(context);
String oaid = adInfo.getId();
获取失败的情况
IMEI获取失败的原因
权限问题
缺少READ_PHONE_STATE权限用户拒绝权限申请Android 6.0+未动态申请权限 版本限制
Android 9+普通应用无法获取需要系统级权限READ_PRIVILEGED_PHONE_STATE 设备问题
无SIM卡设备(平板、WiFi设备)模拟器环境硬件故障 系统限制
厂商定制ROM限制企业级设备管理安全沙箱环境
ANDROID_ID获取失败的原因
系统问题
系统异常某些设备返回固定无效值 应用问题
应用权限被系统限制系统级应用冲突
OAID获取失败的原因
厂商支持问题
设备厂商未实现OAID系统版本过低,厂商未提供OAID支持小众厂商或海外设备 用户设置问题
用户启用了"限制广告追踪"用户在系统设置中重置了广告标识符隐私设置限制了标识符获取 系统问题
系统异常或MSA服务未正常运行某些定制ROM可能限制OAID获取 应用问题
未正确集成MSA SDKSDK版本过旧或兼容性问题
业务场景选择
适合使用IMEI的场景
✅ 需要跨应用卸载重装的设备绑定✅ 用户身份识别✅ 需要长期稳定的设备标识✅ 反作弊、风控等安全场景
适合使用ANDROID_ID的场景
✅ 应用内用户行为追踪✅ 需要相对稳定的设备标识(Android 8.0+)✅ 注重隐私保护的场景✅ 无需申请权限的场景⚠️ Android 8.0以下系统的临时标识场景
适合使用OAID的场景
✅ 国内应用市场,特别是广告相关业务✅ 需要设备级别唯一标识但无法获取IMEI的场景✅ 符合国内隐私政策要求的场景✅ 需要跨应用卸载重装保持一致的设备标识
对比表
特性IMEIANDROID_IDOAID唯一性级别设备级别应用级别设备级别持久性高(硬件级别)中(应用级别,Android 8.0+基于签名)高(设备级别)卸载重装后不变Android 8.0+不变,8.0以下会改变不变需要权限✅ 需要❌ 无需❌ 无需隐私安全❌ 可能泄露设备信息✅ 隐私友好✅ 隐私友好版本兼容性❌ Android 10+受限✅ 全版本支持✅ 厂商支持即可获取成功率中(受权限影响)高(无需权限)中(受厂商支持影响)国内支持✅ 全设备支持✅ 全设备支持✅ 主流厂商支持海外支持✅ 全设备支持✅ 全设备支持❌ 主要支持国内
常见问题解答
Q1: 为什么有时候获取不到设备ID?
A: 主要原因包括:
缺少必要权限(IMEI需要READ_PHONE_STATE权限)用户拒绝权限申请Android版本限制(Android 10+普通应用无法获取IMEI)设备硬件问题(无SIM卡、模拟器等)厂商不支持OAID(OAID主要支持国内主流厂商)
Q2: IMEI、ANDROID_ID和OAID哪个更好?
A: 各有优势,需要根据业务场景选择:
OAID:国内应用推荐,设备级别唯一,无需权限,卸载重装不变IMEI:适合需要长期稳定标识的场景,但需要权限且Android 10+受限ANDROID_ID:适合应用内标识,无需权限,但卸载重装会改变
Q3: 卸载重装应用后,ANDROID_ID会改变吗?
A: 取决于Android版本:
Android 8.0 (API 26) 及以上:不会改变。ANDROID_ID基于应用签名密钥、用户和设备生成,相同签名的应用重装后获得相同的ANDROID_IDAndroid 8.0以下:会改变。卸载应用时会被清除,重装时重新生成
这是Android 8.0的重要变更,目的是为应用提供更稳定的标识符。
Q4: OAID卸载重装会变吗?
A: 大多数情况下不会变。OAID是设备级别的标识符,与设备绑定而非应用绑定。但在以下情况下可能会变化:
用户主动在系统设置中重置广告标识符系统大版本更新后厂商重新生成OAID用户修改了隐私设置
Q5: 如何确保设备标识的稳定性?
A: 建议采用多重备选方案:
优先使用OAID(国内设备推荐)备选使用ANDROID_ID(无需权限)最后使用UUID(随机生成)在本地存储中缓存结果
Q6: 在接口传参中应该使用哪个?
A: 建议根据业务需求选择:
国内应用:优先使用OAID,备选ANDROID_ID海外应用:使用ANDROID_ID用户识别场景:优先使用OAID,备选ANDROID_ID应用内统计:使用ANDROID_ID即可跨应用场景:必须使用OAID隐私敏感场景:优先使用OAID或ANDROID_ID用到IMEI的场景:仅开发系统app,定制ROM可使用。
Q7: OAID需要Android 10以上才能获取吗?
A: 不需要。OAID的获取主要取决于设备厂商的实现,而非Android系统版本。许多厂商在Android 8.0、9.0系统上也实现了OAID支持。
总结
设备标识符的选择需要综合考虑业务需求、权限要求、版本兼容性、隐私保护和地域特点等因素。对于国内应用,推荐优先使用OAID;对于海外应用,推荐使用ANDROID_ID。
关键要点:
OAID是国内应用的最佳选择,设备级别唯一且无需权限IMEI需要权限,但设备级别唯一,Android 10+受限ANDROID_ID在Android 8.0+卸载重装后不会改变(重要更新)ANDROID_ID无需权限,Android 8.0+基于应用签名生成,具有较好的稳定性建议结合多种方案实现稳定的设备标识注意Android版本的兼容性问题,特别是8.0的重大变更