Android Management API部分设备无法获取serialNumber问题求助
设备序列号获取失败的排查与解决方案
问题背景
使用Android Management API获取设备序列号时,部分机型(如Samsung A30、Samsung Active Tab 3)可正常返回,但Redmi Pro 10、Samsung SM-G781B等机型无法获取,已配置管理应用策略、Manifest权限及相关读取代码。
权限配置修正
1. 补全管理应用策略中的权限授权
当前策略未包含读取设备状态的核心权限,需更新为:
{ "installType": "REQUIRED_FOR_SETUP", "permissionGrants": [ { "policy": "GRANT", "permission": "android.permission.PACKAGE_USAGE_STATS" }, { "policy": "GRANT", "permission": "android.permission.READ_PHONE_STATE" }, { "policy": "GRANT", "permission": "android.permission.READ_PRIVILEGED_PHONE_STATE" } ], "autoUpdateMode": "AUTO_UPDATE_HIGH_PRIORITY", "defaultPermissionPolicy": "GRANT", "packageName": "com.example.management", "delegatedScopes": [ "CERT_INSTALL" ] }
注意:
READ_PRIVILEGED_PHONE_STATE属于特权权限,仅系统应用或通过Android Management API部署的设备所有者应用可获取,必须在策略中明确授权。
2. 优化Manifest权限声明
移除冗余的版本限制配置,确保权限声明清晰:
<uses-permission android:name="android.permission.CALL_PHONE" /> <uses-permission android:name="android.permission.READ_PRIVILEGED_PHONE_STATE" tools:ignore="ProtectedPermissions" /> <uses-permission android:name="android.permission.READ_PHONE_STATE" />
代码逻辑修复
1. 补充厂商特定系统属性键
不同厂商的序列号存储属性键存在差异,需增加适配:
fun getDeviceSerial(applicationContext: Context): String { var serialNumber: String = "" try { val c = Class.forName("android.os.SystemProperties") val get = c.getMethod("get", String::class.java) serialNumber = get.invoke(c, "gsm.sn1") as String when (serialNumber) { "" -> serialNumber = get.invoke(c, "ril.serialnumber") as String "" -> serialNumber = get.invoke(c, "ro.serialno") as String "" -> serialNumber = get.invoke(c, "sys.serialnumber") as String "" -> serialNumber = get.invoke(c, "ro.boot.serialno") as String // 适配部分三星机型 "" -> serialNumber = get.invoke(c, "ro.miui.serialnumber") as String // 适配小米机型 } @Suppress("DEPRECATION") if (serialNumber.isEmpty()) { serialNumber = Build.SERIAL } } catch (e: Exception) { e.printStackTrace() serialNumber = "" } // 处理"unknown"情况 if (serialNumber == "unknown") { try { val c = Class.forName("android.os.SystemProperties") val get = c.getMethod("get", String::class.java, String::class.java) serialNumber = get.invoke(c, "ril.serialnumber", "unknown") as String } catch (ignored: Exception) { ignored.printStackTrace() } } // Android O+官方API读取 try { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O && serialNumber == "unknown") { val hasPhonePerm = ActivityCompat.checkSelfPermission( applicationContext, Manifest.permission.READ_PHONE_STATE ) == PackageManager.PERMISSION_GRANTED val hasPrivilegedPerm = ActivityCompat.checkSelfPermission( applicationContext, Manifest.permission.READ_PRIVILEGED_PHONE_STATE ) == PackageManager.PERMISSION_GRANTED if (hasPhonePerm || hasPrivilegedPerm) { serialNumber = Build.getSerial() } } } catch (e: Exception) { serialNumber = "" } return serialNumber }
2. 修正权限检查逻辑
openTelePhony中错误使用CALL_PHONE权限判断,需替换为设备状态权限:
fun openTelePhony(context: Context?) { context?.let { var a = "" try { val hasPhonePerm = ContextCompat.checkSelfPermission( context, Manifest.permission.READ_PHONE_STATE ) == PackageManager.PERMISSION_GRANTED val hasPrivilegedPerm = ContextCompat.checkSelfPermission( context, Manifest.permission.READ_PRIVILEGED_PHONE_STATE ) == PackageManager.PERMISSION_GRANTED a = if (hasPhonePerm || hasPrivilegedPerm) { getDeviceSerial(context) } else { @Suppress("DEPRECATION") Build.SERIAL } System.out.print(a) } catch (e: Exception) { e.printStackTrace() } } }
额外排查方向
- 厂商系统限制:部分小米、三星机型会在系统层面限制序列号读取,需确认设备的企业管理设置或开发者选项中未禁用相关权限。
- 设备所有者身份:确保管理应用通过Android Management API被设置为设备所有者,非设备所有者应用无法获取特权权限。
- 系统版本适配:Android 10+对隐私权限管控更严格,需确保所有必要权限均通过管理策略授予,且应用已完成权限初始化。
内容的提问来源于stack exchange,提问作者Suman Neupane
相关产品推荐
相关产品推荐

