Android 8.0 以上获取设备序列号

问题原因

  • 今日在 APP 登录中,一直登录不上,提示序列号异常(内部提醒),一直很奇怪,代码几乎没动过任何代码;逛了一圈代码,最后才发现是自己的设备升级到了 Android 8.0 (Android O) 以上,导致获取不到序列号;
  • 本文章进行总结下从 Android 4.4 - Android 9.0 版本中适配获取序列号(SN) 的方法

因为 APP 会针对序列号进行限制设备使用(方便辨识)

代码变更

现写法

1
2
3
4
5
6
7
8
9
10
11
12
public void setSerialNumber() {
String serial = null;
try {
Class c = Class.forName("android.os.SystemProperties");
Method get = c.getMethod("get", String.class);
serial = (String) get.invoke(c, "ro.serialno");
} catch (Exception e) {
e.printStackTrace();
Log.e(Constants.LOG_TAG, "获取设备序列号失败");
}
this.serialNumber = serial;
}
  • 如果你在 Android 8.0 以上的版本运行,它会一直报 Access denied finding property "ro.serialno" 这个错,原因是 Android O 为了更好的管理用户的隐私做了一些调整,通过 Build.SERIAL 来进行获取序列号,很便捷;

改进后

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
public void setSerialNumber() {
String serial = null;
try {
if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) { // 9.0 +
serial = Build.getSerial();
} else if (Build.VERSION.SDK_INT > Build.VERSION_CODES.N) { // 8.0 +
serial = Build.SERIAL;
} else { // 8.0 -
Class c = Class.forName("android.os.SystemProperties");
Method get = c.getMethod("get", String.class);
serial = (String) get.invoke(c, "ro.serialno");
}
} catch (Exception e) {
e.printStackTrace();
Log.e(Constants.LOG_TAG, "获取设备序列号失败");
}
this.serialNumber = serial;
}

知识补充

  • 为了与访问 IMEI 所需的运行时权限保持一致,对于针对 Android O 或更新版本的应用,现已弃用 android.os.Build.SERIAL。它们可以改为使用新的 Android O API,即Build.getSerial(),只要调用方拥有 PHONE 权限,该函数将返回实际序列号。在未来版本的 Android 中,针对 Android O 的应用所查询到的 Build.SERIAL 将显示为“UNKNOWN”。为避免中断旧版应用的正常工作,针对以前版本 Android 的应用所查询到的设备序列号仍和以前一样。

意思也就是,在 Android O 版本上也可以通过 Build.getSerial() 进行获取序列号;

  • 通过 Build.getSerial() 的调用获取需要调用方拥有PHONE权限
1
<uses-permission android:那么="android.permission.READ_PHONE_STATE" />

最后

  • 因个人 APP 的版本使用的,使用的 api 版本较低,所以在 P 和 O 版本中获取序列号进行了区别;
  • 各位可直接使用 Build.getSerial() 进行获取,避免后续版本的更新导致获取为 “UNKNOWN” 的情况