设备ID,简单来说就是一串符号(或者数字),映射现实中硬件设备。
如果这些符号和设备是一一对应的,可称之为“唯一设备ID(Unique Device Identifier)”

不幸的是,对于Android平台而言,没有稳定的API可以让开发者获取到这样的设备ID。
开发者通常会遇到这样的困境:
随着项目的演进, 越来越多的地方需要用到设备ID;
然而随着Android版本的升级,获取设备ID却越来越难了。
加上Android平台碎片化的问题,获取设备ID之路,可以说是步履维艰。

二、设备ID的作用

关于设备ID的作用,大概可以分为下面几点:

  • 统计需求

统计需求是设备ID最常见的用途,包括DAU, MAU的统计,行为统计,广告激活的统计等。

  • 业务需求

设备ID通常也用于业务中。
比如结合行为统计做用户画像,以为用户提供个性化的服务,大家感受比较明显的就是新闻类和电商类的APP了。
这类操作,有利有弊,仁者见仁智者见智。
又如,定向推送,不一定是广告推送,错误修复,内测推送等也会用到设备ID。
还有是一些和特定业务结合的用途,比如构造分布式ID等。

  • 风控需求

设备ID还可用于防刷单,反作弊等。
当然,风控需求仅靠设备ID是无法完成的,通常需要建立一套反作弊系统。
关于这方面的内容,难以一言以蔽之,这里我们不多作展开。

三、获取设备ID的API

获取设备标识的API屈指可数,而且都或多或少有一些问题。
常规的API有以下这些:

IMEI

IMEI本该最理想的设备ID,具备唯一性,恢复出厂设置不会变化(真正的设备相关)。
然而,获取IMEI需要 READ_PHONE_STATE 权限,估计大家也知道这个权限有多麻烦了。
尤其是Android 6.0以后, 这类权限要动态申请,很多用户可能会选择拒绝授权。
我们看到,有的APP不授权这个权限就无法使用, 这可能会降低用户对APP的好感度。
而且,Android 10.0 将彻底禁止第三方应用获取设备的IMEI, 即使申请了 READ_PHONE_STATE 权限。
所以,如果是新APP,不建议用IMEI作为设备标识;
如果已经用IMEI作为标识,要赶紧做兼容工作了,尤其是做新设备标识和IMEI的映射。

设备序列号

通过android.os.Build.SERIAL获得,由厂商提供。
如果厂商比较规范的话,设备序列号+Build.MANUFACTURER应该能唯一标识设备。 但现实是并非所有厂商都按规范来,尤其是早期的设备。
最致命的是,Android 8.0 以上,android.os.Build.SERIAL 总返回 “unknown”;
若要获取序列号,可调用Build.getSerial() ,但是需要申请 READ_PHONE_STATE 权限。
到了Android 10.0以上,则和IMEI一样,也被禁止获取了。
总体来说,设备序列号有点鸡肋:食之无味,弃之可惜。

MAC地址

获取MAC地址也是越来越困难了,
Android 6.0以后通过 WifiManager 获取到的mac将是固定的:02:00:00:00:00:00 ,
再后来连读取 /sys/class/net/wlan0/address 也获取不到了。
如今只剩下面这种方法可以获取(没有开启wifi也可以获取到):

public static String getWifiMac() {
try {
Enumeration enumeration = NetworkInterface.getNetworkInterfaces();
if (enumeration == null) {
return “”;
}
while (enumeration.hasMoreElements()) {
NetworkInterface netInterface = enumeration.nextElement();
if (netInterface.getName().equals(“wlan0”)) {
return formatMac(netInterface.getHardwareAddress());
}
}
} catch (Exception e) {
Log.e(“tag”, e.getMessage(), e);
}
return “”;
}

再往后说不准这种方法也行不通了,且用且珍惜~

ANDROID_ID

Android ID 是获取门槛最低的,不需要任何权限,64bit 的取值范围,唯一性算是很好的了。
但是不足之处也很明显:
1、刷机、root、恢复出厂设置等会使得 Android ID 改变;
2、Android 8.0之后,Android ID的规则发生了变化:

  • 对于升级到8.0之前安装的应用,ANDROID_ID会保持不变。如果卸载后重新安装的话,ANDROID_ID将会改变。
  • 对于安装在8.0系统的应用来说,ANDROID_ID根据应用签名和用户的不同而不同。ANDROID_ID的唯一决定于应用签名、用户和设备三者的组合。

两个规则导致的结果就是:
第一,如果用户安装APP设备是8.0以下,后来卸载了,升级到8.0之后又重装了应用,Android ID不一样;
第二,不同签名的APP,获取到的Android ID不一样。
其中第二点可能对于广告联盟之类的有所影响(如果彼此是用Android
ID对比数据的话),所以Google文档中说“请使用Advertising ID”,
不过大家都知道,Google的服务在国内用不了。

对Android ID做了约束,对隐私保护起到一定作用,并且用来做APP自己的活跃统计也还是没有问题的。

四、 设备ID的特性分析

笔者之前写过一篇文章《Android设备唯一标识的获取和构造》, 文中提到设备ID的两个概念:唯一性和稳定性。

4.1 唯一性

唯一性: 两台不同的设备获取到的设备ID不相同。

分析唯一性,我们可以从ID的分配来入手:

  • 1、按规则构造

比如自增ID(包括分步自增),分段构造的ID(如snowflake算法)等,此类ID能保证唯一性。
设备ID中的IMEI,设备序列号,MAC等,都是按照规则构造的,理论上能保证唯一性。
设备序列号是对厂商本身唯一,全局唯一需要在加上 Build.MANUFACTURER
不过,设备序列号和MAC的唯一要打个问号,因为要看厂商是否遵守规则。
但随着手机产业的日渐成熟,传统意义上的山寨设备已越来越少,所以大多数情况下还是唯一的。

  • 2、随机生成

比如UUID和Android ID,这类ID有一定的概率会重复,关键是看ID的长度(有多少bit)。
有人做了这样一张随机数的冲突概率表:

左边第一栏是bit数量,第二栏是对应的取值范围,再后面是元素个数以及对应的冲突概率。
例如,假如有50000个32bit的随机数,则这些随机数中,至少有两个相同数字的概率为25%;
换一种说法,就是假如有四组数,每组都有50000个随机数,则大约其中一组会有重复的数字。
32bit有43亿的取值范围,怎么50000个随机数就有这么高的出现重复的概率?
如果对此感到困惑,可以了解一下生日悖论。

Android ID是长度为16的十六进制字符串,其实就是64bit,我们来分析一下其重复的概率:
假如APP累计激活量达到50亿的APP,则每两个这样的APP就大约有一个会有重复的Android ID。
不过这里的“重复”不是大量的重复,而是“至少有两个相同”,也就是,如果设备激活量有50亿(很多APP达不到-_-),那么有可能会有少量的重复的Android ID。
总体而言, Android ID的唯一性还是不错的。
JDK的randomUUID,大致可以认为是128bit的随机数(其中有6bit是固定的),即使到达200亿的数量,有重复的概率也仅仅是10的负18次方,微乎其微。

4.2 稳定性

稳定性:同一台设备在不同的时间, 获取到设备ID相同。

稳定性有两个层面:

  • 1、ID的生命周期

IMEI,序列号,MAC等都是硬件相关,即使刷机也不会改变;
Android ID则稳定性较弱,恢复出厂设置和刷机都会改变Android ID。

  • 2、受版本的变化的影响

随着Android版本的提升,Google对权限是越收越紧了。
获取设备ID的API,要么收起不给用(IMEI), 要么获取变得困难(SERIAL
),要么不同签名的APP获取的值不一样(Android ID)。
同时,Android 10中存储权限也收缩了,之前的那种生成唯一ID写到SD卡的某个角落的,以求卸载重装后读之前的ID等方法也不奏效了。
加强隐私方面的权限,对用户而言是好事,但对开发者而言就比较难受了。
尤其是有的API本来可以用,升级后就获取不到了,这种断崖式的变化,可能会对数据统计造成影响。

五、设备ID的构造

无论是统计需求,还是业务需求,都要求设备ID是唯一的,稳定的。
如果设备ID有重复,则活跃统计,用户画像,定向推送等统统都不准确了;
其中,影响最深是定向推送,送错快递还有可能追回,推送错了就不好说了,如果推送内容又比较重要,后果不堪设想。
如果设备ID不稳定(ID变化),会
影响到活跃统计(会认为是新用户),对用户画像也有较大影响(之前的ID关联的行为数据无法跟踪了)。

为此,有必要设计一套方案,提供相对定稳定的,唯一的设备ID。
首先要明确两个前提条件:
前面分析的设备ID中,在可用的前提下,出现重复的概率较小;
如果一定的频率去观察,比如说每天,总体而言,观察到和昨天不一样的概率也是较小的。
如何在本来就较小的概率的前提下,继续降低概率呢?

5.1 方案分析

一种方案是组合设备ID(直接拼接,或者拼接后计算摘要)。
举个例子,假如出现重复的概率和发生变化的的概率都是千分之一,
则对于两台不同设备,两个设备ID同时重复的概率是百万分之一,两个设备ID至少有一个发生变化约为千分之二。
也就是,拼接ID的效果是大大提高唯一性,但是一定程度上降低稳定性(只要其中一个要素变化,拼接的ID就变了)。
但事实上,如今能拿到的设备ID,最突出的矛盾是不稳定,所以,我们不能为了提高唯一性而牺牲稳定性。

要提高稳定性,可以引入容错方案。
容错方案有很多,比如网络传输,用checksum去校验报文,如果出错了则重发;
再如磁盘阵列,数据写入两个磁盘,只有当两个磁盘同时出错时才会丢失数据,从而大大降低丢失数据的概率。
但是对于设备ID,以上两种方案都不合适,因为上面的方案需要通过checksum来确认原信息是否被修改,设备ID没有这样的条件。

所以,可以引入类似虚拟货币用到的"拜占庭容错"方案。
简单地说,就是要采集三个设备ID到云端,如果有两个(包括两个以上)的设备ID和之前的记录相同,则认为是同一台设备。
同样假设出现重复的概率和发生变化的的概率都是千分之一,则:
同一台设备的两次采集,认不出是同一台设备的条件为“至少两个设备ID都和上次不一样”,概率约为百万分之三。
两台不同的设备,认为是同一台的条件是为“三个设备ID中,至少有两个设备ID和另一台设备相同”,概率同样约为百万分之三。
所以,用此方案,唯一性和稳定性都能得到提高。
之前的记录相同,则认为是同一台设备。
同样假设出现重复的概率和发生变化的的概率都是千分之一,则:
同一台设备的两次采集,认不出是同一台设备的条件为“至少两个设备ID都和上次不一样”,概率约为百万分之三。
两台不同的设备,认为是同一台的条件是为“三个设备ID中,至少有两个设备ID和另一台设备相同”,概率同样约为百万分之三。
所以,用此方案,唯一性和稳定性都能得到提高。

漫谈唯一设备ID,android开发工程师相关推荐

  1. Android专业获取设备信息如:AndroidID、唯一设备ID、制造商、型号、版本号、版本码等

    在开发app中很多时候需要获取设备的基本信息等运用到项目中,就需要一些方法获取,网上资源中方法五花八门,有的还获取不到,令人头大,话不多说,鄙人整理了一套方法,话不多说真机测试如下>上图: 接下 ...

  2. android用户界面组件都是放置在,Android开发工程师第十章 节 用户界面高级组件.ppt...

    Android开发工程师第十章 节 用户界面高级组件.ppt 电子相册的设计与实现 4.图片放大与缩小显示的实现 在触摸ImageSwitcher中显示的图片后,全屏显示该图片,要全屏显示该图片,只要 ...

  3. 从零到壹逆袭Android开发工程师

    欢迎查看E·udemon在线博客 你好! 从零到壹逆袭Android开发工程师系列博客,主要以Android Studio为工具进行记录分享,欢迎对Android开发感兴趣的朋友和作者一起交流分享,也 ...

  4. android应用程序判断题,Android开发工程师笔试判断题

    Android开发工程师笔试判断题20例 1.一个Activity就是一个可视化的界面或者看成是控件的容器.√ 2.Intent有很长的生命周期,是没有用户界面的程序,可以保持应用在后台运行,而不会因 ...

  5. Android开发工程师vs运维工程师

    关于我 目录 1.什么是运维工程师 2.什么是Android开发工程师 未完待续 1.什么是运维工程师 对于初创公司,运维工程师的工作可能需要从申请域名开始,购买/租用服务器,上架,调整网络设备的设置 ...

  6. Android 开发工程师面试指南

    原文链接:https://github.com/GeniusVJR/LearningNotes <Android 开发工程师面试指南 LearningNotes >,作者是知乎Androi ...

  7. 如何成为android开发工程师,android开发工程师薪资 如何成为一名合格的android开发工程师?...

    行业薪酬的影响因素包括行业内.外部因素及员工个人的因素,同样,在IT行业中,要想了解android开发工程师的薪资待遇情况如何,我们也可以从这几个因素入手,加以了解.android开发工程师薪资,如何 ...

  8. Android开发工程师面试指南

     Android开发工程师面试指南 功能介绍     给Android开发工程师的一份面试指南,包含面试题集与简历模板. 面试题集 面试题集里的答案大部分来源于我的博客,因此这个题集也相当于是我的博客 ...

  9. 2012年全国最新Android开发工程师薪资水平调查分析

    为什么80%的码农都做不了架构师?>>>    2012年全国最新Android开发工程师薪资水平调查分析 最近几年,随着Android的飞速发展,伴随着巨大的产业需求,国内Andr ...

最新文章

  1. arm b bl 地址无关码_ARM_异常和中断
  2. 高校新校园网络系统设计方案
  3. CCF C³:创业公司如何面对开源?知乎CTO李大海:谢邀
  4. 运算方法和运算部件三
  5. TextVQA论文汇总
  6. oracle时间运算
  7. Windows XP系统超强支持工具全面接触
  8. Linux系统下ifconfig和route配置网络详解
  9. 【java】窗口和监听器的使用
  10. GitLab+Nornor3.0.0完成CI/CD流水线配置(更新版)
  11. Ubuntu20.04安装Redis
  12. linux下的二进制文件查看器
  13. PASCAL VOC2012数据集介绍与制作自己的数据集
  14. 神经网络控制系统的特点,神经网络控制的优点
  15. angular/js/vue ---表格内部换行
  16. ORACLE 完美卸载
  17. 第五次项目《超市会员管理Plus》
  18. Win10 使用双宽带和双网卡进行网络叠加、提高网速的设置
  19. 网页中的动漫人物互动——看板娘
  20. 系统集成项目管理工程师高频考点(第八章)

热门文章

  1. 小牛情报APP最强攻略
  2. 节能减排社会实践 与科技竞赛作品申报书
  3. C++线性表(单链表)的应用算法(附源码)
  4. JedisNoReachableClusterNodeException: No reachable node in cluster
  5. 不再盯着男性发烧友,小米手机要去“撩妹”?
  6. 云视频会议已成未来发展必然趋势
  7. 电大计算机专业毕业自我鉴定,广播电视大学毕业自我鉴定3篇
  8. 工程测量测绘乙级按照标准办理
  9. redis链接不上,报保护模式
  10. Python实用模块