Android(安卓)8、Android(安卓)9获取手机序列号的兼容写法
随着Android 版本的更新,获取手机序列号的方式也有所不同。最近咋工作中看到了,查阅资料在这里总结下目前。
一、获取序列号
public class MainActivity extends AppCompatActivity { private static final String TAG = MainActivity.class.getSimpleName(); private static final int CODE_READ_PHONE_STATE = 0x11; private String serialNumber = "UNKNOWN"; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); getSerialNumber(); } @RequiresApi(api = Build.VERSION_CODES.O) public void checkPermission() { if (checkSelfPermission(Manifest.permission.READ_PHONE_STATE) != PackageManager.PERMISSION_GRANTED) { requestPermissions(new String[]{Manifest.permission.READ_PHONE_STATE}, CODE_READ_PHONE_STATE); } else { serialNumber = Build.getSerial(); } } @RequiresApi(api = Build.VERSION_CODES.O) @SuppressLint("MissingPermission") @Override public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) { if (requestCode == CODE_READ_PHONE_STATE && grantResults[0] == PackageManager.PERMISSION_GRANTED) { serialNumber = Build.getSerial(); } else { Log.i(TAG, "you deny the permission:READ_PHONE_STATE"); } } @SuppressLint("HardwareIds") public String getSerialNumber() { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {// android Q(安卓10) // TODO use yourself style } else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O_MR1) { // android O_MR1(安卓8.1)、android P(安卓 9) checkPermission(); } else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O){// android O(安卓 8.0) this.serialNumber = Build.SERIAL; }else {//below android 8.0 try { // 方式1:执行adb 命令获得 Runtime runtime = Runtime.getRuntime(); Process process = null; process = runtime.exec("getprop ro.serialno"); InputStream is = process.getInputStream(); InputStreamReader isr = new InputStreamReader(is); BufferedReader br = new BufferedReader(isr); this.serialNumber = br.readLine(); // 方式2:反射获得(不推荐使用)// Class<?> c = Class.forName("android.os.SystemProperties");// Method get = c.getMethod("get", String.class);// serialNumber = (String) get.invoke(c, "ro.serialno");// Log.i(TAG, " sdk version low android O ,reflect get" + serialNumber); } catch (IOException e) { e.printStackTrace(); } } return serialNumber; }}
二、测试过程及其结论
1、有关Build.SERIAL字段获取方式
测试结论:
1、安卓8.0及8.0以下可以获得结果。
2、安卓8.1及其以上返回UNKNOWN
文档说明:如下图。
3、8.0时废弃啦,8.0及其以上版本建议使用getSerial()方法代替。
个人结论
8.0还可以用这个方式获取,因为getSerial()方式需要“read phone state” 权限,而读取手机权限时总要去让用户决定,相对来说有点限制。
2、有关Build.getSerial()获取方式
(1)测试结论
1、安卓10(api 29)手机上直接崩溃(api28以上)
2、安卓8.0(api 26)、安卓9(api 28)上可以获得,需要“read phone state” 权限,否则崩溃
小结论:Build.getSerial()是安卓8.0-9.0上Build.SERIAL废弃后的替代方案。
(2)Build.getSerial()的官方api参考
1、Requires Permission: READ_PRIVILEGED_PHONE_STATE2、If the calling app's target SDK is API level 28 or lower and the app has the READ_PHONE_STATE permission then {@link Build#UNKNOWN} is returned.3、If the calling app's target SDK is API level 28 or lower and the app does not have the READ_PHONE_STATE permission, or if the calling app is targeting API level 29 or higher, then a SecurityException is thrown
1、需要READ_PRIVILEGED_PHONE_STATE(READ_PHONE_STATE也行)
2、如果调用应用程序的目标SDK是API级别28或更低,并且应用程序具有READ_PHONE_STATE权限,那么返回#UNKNOWN
3、如果调用应用程序的目标SDK是API级别28或更低,且应用程序没有READ_PHONE_STATE权限,或者如果调用应用程序的目标API级别29或更高,则抛出SecurityException。
ps:总感觉官方这段注释写的有点怪怪的(参考上述个人测试结论)
3、有关8.0以下获取方式
(1)Build.SERIAL获取
这种获取方式支持到8.0及其以下,但会8.0以下网上文章好多都使用反射获得,这里大家合理选择吧!!!
(2)adb 命令或者反射获取测试
1、二者在8.0(>=8.0)版本上获取值为空,8.0以下可以获得
2、不建议使用反射方式获取。(如下图)
4、有关10.0及其更高版本的替代方案
这里建议自己实现:
实现参考如下:
1、官方建议
2、前人实践
The end
给出了自己总结的一种方案,,,,,溜溜球。
更多相关文章
- ConstraintLayout 使用可视化的方式来编写Android应用程序的界面
- Android(安卓)studio 3.1.3 无法获取pom文件
- Android添加快捷方式(Shortcut)到手机桌面
- Android布局之LinearLayout
- View常见XML属性及相关方法
- Android(安卓)获取手机唯一标识(仅限IMEI)
- JS与Android交互之html页面跳转到Android(安卓)Activity
- Android存储权限
- Android(安卓)控件之DatePicker,TimePicker,Calender