起因
我们在做移动端开发时, 不可避免地会遇到需要获取设备唯一标识的问题
如果仅仅只需要给设备去重, 通常情况下我们可以考虑直接使用推送SDK
生成的设备Token
, 比如极光推送, 或者腾讯TPNS
, App
重装后这个token
可能会变, 但重复的概率极低 只是并不具备唯一性
想要唯一性 以安卓设备为例, 其实有很多设备码可用, 比如IMEI
, MAC地址
等等, 但是为什么我们在实际应用中无法将它们用作唯一标识呢
我们挨个来分析一下
IMEI
Android中
也叫DEVICE_ID
, 是移动电话的唯一设备码, 相当于手机的身份证, 具备唯一性
但是:
- 有通话功能的设备才有该码, 不是所有移动设备都具备拨号功能
- 双卡双待会有两个
IMEI
值 - 模拟器可以修改
IMEI
Android10
以上无法获取IMEI
网卡 Mac地址
其中包含硬件MAC
地址和WLAN MAC
地址(BSSID
), 硬件MAC
地址和硬件绑定, 具备唯一性 , 但是WLAN MAC
地址通常是随机的 主要是为了避免隐私泄露, 每个热点在连接时会使用随机的地址
可即便是硬件Mac
也存在不足之处:
- 有网卡的设备才有
Mac
地址, 不是所有设备都具备联网功能 Mac
地址可以通过软件欺骗性修改
蓝牙Mac地址
和WLAN Mac
一样具备唯一性
但是:
- 没有蓝牙的设备获取不到该值
- 蓝牙需要保持开启状态才有值
ANDROID_ID
官方推荐使用的设备码, 具备唯一性
但是:
- 设备恢复出厂设置 或者
ROOT
后 该值会改变 - 国内定制系统的设备可能返回
null
Android8
以下无法获取Android_ID
PsuedoID
该方式是通过拼接硬件信息获取到的,代码如下:
1 | //获得独一无二的Psuedo ID |
最终会得到类似于这样的一串ID:00000000-088ee-388eb-ffff-ffffe93ee2
这种方案只能做到小范围内唯一
因为:
- 系统升级后 该值可能会变化
- 同一批次出厂的设备可能出现值重复
总体来说 该方案可行性相对较高一些 重复的概率极低, 而且不需要获取用户权限
但是依然不够唯一
总结
以上所有的方案似乎都只是理论唯一, 真要用到实际产品中还是差了点, 如果非要准确一些可以考虑以下方案:
第一种
Android 8.0
以下 使用PsuedoID + DeviceId
来判断设备唯一性- Android 8.0及以上 使用
PsuedoID + ANDROID_ID
来判断设备唯一性
第二种
如果忽略大部分不能联网的设备, 可以使用Mac
地址作为唯一标识, 由于Android6.0
以上的版本无法获取Mac
地址, 我们可以考虑从底层文件获取, Mac
地址文件路径为:
1 | /sys/class/net/wlan0/address |
具体代码如下:
1 | fun getMacAddr(): String { |
第三种
使用第三方设备唯一标识提供商, 比如数字联盟, 对于Android
和IOS
设备均适用
本文为作者原创转载时请注明出处 谢谢