1、获取imei:
前言:
因传统的移动终端设备标识如国际移动设备识别码(IMEI)等已被部分国家认定为用户隐私的一部分, 并存在被篡改和冒用的风险,所以在Android 10及后续版本中非厂商系统应用将无法获取IMEI、MAC等设备信息。
无法获取IMEI会在用户行为统计过程中对设备识别产生一定影响。 移动安全联盟针对该问题联合国内手机厂商推出补充设备标准体系方案, 选择OAID字段作为IMEI等的替代字段。
OAID字段是由中国信通院联合华为、小米、OPPO、VIVO等厂商共同推出的设备识别字段,具有一定的权威性,可满足用户行为统计的使用场景。
总结:
private static String getImei(Context context) { if (Build.VERSION.SDK_INT < Build.VERSION_CODES.Q) { return DeviceIdentifier.getIMEI(context); } else return DeviceIdentifier.getOAID(context); }
2、获取androidId:
前言:
在设备首次启动时,系统会随机生成一个64位的数字,并把这个数字以16进制字符串的形式保存下来。
不需要权限,平板设备通用。获取成功率也较高,缺点是设备恢复出厂设置会重置。
另外就是某些厂商的低版本系统会有bug,返回的都是相同的AndroidId。
厂商定制系统的Bug:不同的设备可能会产生相同的ANDROID_ID:9774d56d682e549c。
厂商定制系统的Bug:有些设备返回的值为null。
设备差异:对于CDMA设备,ANDROID_ID telephonyManager.getDeviceId() 返回相同的值。 它在Android <=2.1 or Android >=2.3的版本是可靠、稳定的,但在2.2的版本并不是100%可靠的。 通常被认为不可信,因为它有时为null。
开发文档中说明了:这个ID会改变如果进行了出厂设置。
并且,如果某个Andorid手机被Root过的话,这个ID也可以被任意改变。
上代码:
String androidID = DeviceIdentifier.getAndroidID(context);
3、如果不区分拿的是imei、oaid、android,只要是唯一Id就可以,那么可以参考下面的方法
public static String getUniqueId(Context context) { String id = null; String androidID = DeviceIdentifier.getAndroidID(context); String oaid = getImei(context); String serial = Build.SERIAL; serial = "unknown".equals(serial) ? "" : serial; if (null != oaid && !"".equals(oaid)) id = oaid; else if (null != androidID && !"".equals(androidID)) id = androidID; id = id + serial; try { return toMD5(id); } catch (NoSuchAlgorithmException e) { e.printStackTrace(); return id; } }
private static String getImei(Context context) { if (Build.VERSION.SDK_INT < Build.VERSION_CODES.Q) { return DeviceIdentifier.getIMEI(context); } else return DeviceIdentifier.getOAID(context); } //看需求,不需要加密就不用添加这个 private static String toMD5(String text) throws NoSuchAlgorithmException { if (null == text || "".equals(text) || "unknown".equals(text)) return "unknown"; //获取摘要器 MessageDigest MessageDigest messageDigest = MessageDigest.getInstance("MD5"); //通过摘要器对字符串的二进制字节数组进行hash计算 byte[] digest = messageDigest.digest(text.getBytes()); StringBuilder sb = new StringBuilder(); for (byte b : digest) { //循环每个字符 将计算结果转化为正整数; int digestInt = b & 0xff; //将10进制转化为较短的16进制 String hexString = Integer.toHexString(digestInt); //转化结果如果是个位数会省略0,因此判断并补0 if (hexString.length() < 2) { sb.append(0); } //将循环结果添加到缓冲区 sb.append(hexString); } //返回整个结果 return sb.toString(); }
有不对或者可以改进的点,望大家指出,仅供参考。