Android 11及以上设备获取非重置唯一标识(IMEI/序列号等)技术咨询
Android 11+ 设备唯一标识解决方案(内部应用场景)
IMEI、序列号及MAC地址的获取限制
Android 11及以上系统对隐私敏感标识的获取做了严格限制:
- 普通应用(即便不上Google Play)无法通过常规权限获取IMEI、序列号或MAC地址,系统会直接返回空值或抛出权限异常。
- 仅当应用拥有设备所有者/Profile所有者权限(通过MDM管理配置)时,才能申请
READ_PRIVILEGED_PHONE_STATE权限,进而读取IMEI和序列号。如果是员工自带设备(BYOD),即便内部应用也无法突破这个限制。
可行的设备唯一标识方案
根据你的内部应用场景,推荐以下几种方案:
1. 自定义持久化UUID
生成一个唯一UUID,首次启动时存储在应用私有存储(SharedPreferences、Room或内部文件)中,卸载前会一直保留。适合用户不会随意卸载的内部应用:
fun getCustomDeviceId(context: Context): String { val prefs = context.getSharedPreferences("InternalAppPrefs", Context.MODE_PRIVATE) var deviceId = prefs.getString("unique_device_id", null) if (deviceId.isNullOrEmpty()) { deviceId = UUID.randomUUID().toString() prefs.edit().putString("unique_device_id", deviceId).apply() } return deviceId }
2. Android ID(签名绑定)
Android 10+中,Settings.Secure.ANDROID_ID对同一签名的应用返回固定值,卸载重装后不会改变,仅在设备重置时失效。如果你的内部应用均使用同一签名,这是个可靠的选项:
fun getAndroidId(context: Context): String? { return Settings.Secure.getString(context.contentResolver, Settings.Secure.ANDROID_ID) }
3. 非敏感硬件信息哈希(备选)
收集CPU型号、屏幕分辨率、内存规格等非隐私敏感的硬件参数,通过哈希算法生成唯一标识。注意:不同设备可能出现哈希碰撞,系统更新也可能导致参数变化,仅作为兜底方案:
fun generateHardwareHash(context: Context): String { val hardwareInfo = StringBuilder().apply { append(Build.BRAND) append(Build.MODEL) append(Build.SUPPORTED_ABIS.firstOrNull() ?: "") append(context.resources.displayMetrics.run { "${widthPixels}x${heightPixels}" }) append(Runtime.getRuntime().maxMemory() / 1024 / 1024) }.toString() return MessageDigest.getInstance("SHA-256") .digest(hardwareInfo.toByteArray()) .joinToString("") { "%02x".format(it) } }
4. 企业管控设备专属方案
如果是企业完全拥有的设备(通过MDM管理):
- 通过MDM平台将你的应用设置为设备所有者或工作资料所有者。
- 申请
READ_PRIVILEGED_PHONE_STATE权限,即可读取IMEI和序列号:
fun getImeiForManagedDevice(context: Context): String? { val telephonyManager = context.getSystemService(Context.TELEPHONY_SERVICE) as TelephonyManager return try { if (ContextCompat.checkSelfPermission(context, Manifest.permission.READ_PRIVILEGED_PHONE_STATE) == PackageManager.PERMISSION_GRANTED) { telephonyManager.imei } else null } catch (e: SecurityException) { null } }
总结
- 非管控内部应用:优先使用自定义持久化UUID或Android ID,无法获取IMEI、序列号或MAC地址。
- 企业管控设备:通过MDM配置权限后可读取IMEI和序列号。
内容的提问来源于stack exchange,提问作者Shaikh Danish
相关产品推荐
相关产品推荐

