Flutter获取Android设备序列号失败,求修正Kotlin方法对接Management API
适配全Android版本获取设备序列号(对应Android Management API映射需求)
修正后的Kotlin函数
fun getSerialNumber(context: Context): String { var serialNumber: String? = null // 优先使用官方API,按版本分支处理 try { when { Build.VERSION.SDK_INT >= Build.VERSION_CODES.O -> { // Android 8.0+:使用Build.getSerial() if (hasRequiredPermission(context)) { serialNumber = Build.getSerial() } } Build.VERSION.SDK_INT >= Build.VERSION_CODES.GINGERBREAD -> { // Android 2.3-7.1:使用Build.SERIAL serialNumber = Build.SERIAL } } } catch (e: SecurityException) { // 权限不足时,尝试 fallback 到系统属性 e.printStackTrace() } // 官方API失败时,尝试读取系统属性(覆盖部分厂商自定义字段) if (serialNumber.isNullOrEmpty() || serialNumber == Build.UNKNOWN) { serialNumber = try { val systemProps = Class.forName("android.os.SystemProperties") val getMethod = systemProps.getMethod("get", String::class.java) // 按优先级尝试不同的系统属性键 listOf( "ro.serialno", "ro.boot.serialno", "sys.serialnumber", "ril.serialnumber", "gsm.sn1", "ro.kernel.androidboot.serialno" ).firstNotNullOfOrNull { key -> val value = getMethod.invoke(systemProps, key) as String if (value.isNotEmpty() && value != Build.UNKNOWN) value else null } } catch (e: Exception) { e.printStackTrace() null } } // 最终校验,返回有效序列号或临时值 return if (!serialNumber.isNullOrEmpty() && serialNumber != Build.UNKNOWN) { serialNumber } else { "TEMP12345678" } } // 检查是否拥有必要权限 private fun hasRequiredPermission(context: Context): Boolean { return when { Build.VERSION.SDK_INT >= Build.VERSION_CODES.R -> { // Android 11+:设备所有者/配置文件所有者无需额外权限,或检查READ_PHONE_STATE context.packageManager.hasSystemFeature(PackageManager.FEATURE_DEVICE_ADMIN) || ContextCompat.checkSelfPermission(context, Manifest.permission.READ_PHONE_STATE) == PackageManager.PERMISSION_GRANTED } Build.VERSION.SDK_INT >= Build.VERSION_CODES.M -> { // Android 6.0-10:检查READ_PHONE_STATE权限 ContextCompat.checkSelfPermission(context, Manifest.permission.READ_PHONE_STATE) == PackageManager.PERMISSION_GRANTED } else -> { // Android 5.1及以下:无需动态权限 true } } }
关键适配要点
- 权限逻辑优化:
- Android 6.0(API23)及以上:必须动态申请
READ_PHONE_STATE权限,仅在Manifest声明无效。 - Android 11(API30)及以上:如果你的应用是设备所有者/配置文件所有者(Android Management API管理的设备默认满足此条件),调用
Build.getSerial()无需额外权限;普通应用受系统限制无法获取真实序列号。
- Android 6.0(API23)及以上:必须动态申请
- API调用优先级:优先使用官方标准API,减少对系统属性的依赖(部分属性在高版本会被系统限制访问)。
- 异常处理增强:单独捕获权限异常,避免反射或API调用失败导致函数崩溃。
- 系统属性 fallback:按优先级尝试常见厂商自定义序列号字段,覆盖更多设备场景。
额外注意事项
- 确保应用已通过Android Management API注册为设备所有者/配置文件所有者,这是Android 10+获取真实序列号的必要前提。
- 移除Manifest中
READ_PRIVILEGED_PHONE_STATE权限,该权限仅授予系统应用或预装应用,第三方应用无法获取。
内容的提问来源于stack exchange,提问作者Shreyansh Sharma
相关产品推荐
相关产品推荐

