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

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管理):

  1. 通过MDM平台将你的应用设置为设备所有者或工作资料所有者。
  2. 申请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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.09 20:40:24