1. 使用场景
1. 业务角度
在业务的推广中,需要对每台设备每个用户进行一个唯一识别码来支持业务场景,但对于每一台设备或者每一个用户的定义各有不同。那针对于不同的业务角度,如何识别一台新设备与一个新的用户加入对App来说是有意义的。
2. 数据采集及分析
对App的数据采集,及后台的数据分析有一个对应关系。
3. 应用系统
应用系统使用,可以定义游客与登录客户的映射关系,或者游客相关的记录存档。
2. 设备ID可选值及问题
目前开发者需要找到获取设备唯一ID的方式,目前从设备来看,可以作为设备唯一性的属性主要有:
Given below are the different types of identifying devices ID in android devices.
Unique number (IMEI, MEID, ESN, IMSI)
MAC Address
Serial Number,SN(设备序列号)
ANDROID_ID
由于国内复杂的ROM定制环境,用户权限拒绝,DeviceID在使用过程中并不能百分百获取到。各种有各种不同的优缺点,具体优缺点分析:
- devices ID
Android设备需要有电话服务,如果刷机了该值不会更改,即使该手机可能刷机给别人正在使用,就可能造成误解,该设备为同一个人使用。
缺点:
如果用户禁用掉相关权限,不能获取到deviceId
使用该deviceId,该识别符为设备硬件相关,即使刷机也不会改变该值。
- The IMEI, MEID, ESN, IMSI can be defined as follows:
IMEI( International Mobile Equipment Identity )
国际移动设备识别码(International
Mobile Equipment Identity,IMEI),即通常所说的手机序列号、手机“串号”,用于在移动电话网络中识别每一部独立的手机等移动通信设备,相当于移动电话的身份证。IMEI是与手机绑定的。
目前GSM/WCDMA/LTE手机终端需要使用IMEI号码,在单卡工程中一个手机号对应一个IMEI号,双卡手机则会对应两个IMEI号,一张是手机卡对应一个。
MEID(Mobile Equipment IDentifier)
Mobile Equipment IDentifier(MEID)是一个全球唯一的56bit移动终端标识号,在手机键盘直接键入*#06#可获得。标识号会被输入终端里,以后可以被修改。可用来对移动式设备进行身份识别和跟踪。由于ESN号段是有限的资源,基本上耗尽,可能还有少量回收利用的号段,所以制定了56位的MEID号段,用来取代32位的ESN号段。MEID主要分配给CDMA制式的手机。
IMSI(International Mobile Subscriber
Identity)
GSM与UMTS网络下移动用户识别码。国际移动用户识别码(IMSI:International Mobile Subscriber
Identification Number)是区别移动用户的标志,储存在SIM卡中,可用于区别移动用户的有效信息。
- Mac地址:
它为设备网卡地址,返回一个Wi-Fi或者蓝牙硬件的Mac地址,但是它不能作为一个唯一设备。
缺点:
必须具备硬件,并非所有设备都有Wi-Fi功能
如果设备有Wi-Fi,但也应该打开否则也获取不到地址
在Android6.0以后 google 为了运行时权限对geMacAddress();作出修改通过该方法得到的mac地址永远是一样的,
- SN:
从Android 2.3(“Gingerbread”)版本后可以通过android.os.Build.SERIAL获取,SN能识别例如MIDs (Mobile Internet Devices) or PMPs (Portable Media Players)没有电话服务的。也可以通过读取” ro.serialno”获取。
缺点:
不是所有设备可用,有些手机出现无用数据。比如红米手机返回的就是连续的非随机数。有些ROM定制机或者rooted设备有时会生成无效数据。
- ANDROID_ID:
通过Settings.Secure.ANDROID_ID获取,一串64位(16进制)的字符串,设备first boot时随机生成,如果恢复出厂设置,或者刷机ROM就是改变该值。
缺点:
手机恢复出厂设置以后该值会发生变化
在国内Android定制的大环境下,有些设备是不会返回ANDROID_ID的
存在一个BUG,在部分设备厂商可能会有相同的ANDROID_ID
综上:
因为Android设备的多系统版本,定制系统复杂,Google Bug,root操作,定制ROM系统,多用户支持。Android设备目前没有统一的一个获取设备ID的方法,不能依靠一个简单的方式获取设备唯一识别码。
3. 生成方案:
- 根据ID生命周期:
deviceID: 与设备强关联,设备不变该值永远不会改变,部分设备也可能为空。
ANDROID_ID:与操作系统关联,如果恢复出厂设置或者root,则该值会改变。
SoftInstalIID: 与应用相关,应用安装即生成SoftInstall的ID,应用卸载后重新安装则该值会改变。
- 根据场景:
原则上来说,刷新手机或者恢复出厂设置都可以让旧用户所有数据丢失,使用可以认为是一台新的机器,可以认定为新的用户使用。
- 尽量ID值不改变
实现:根据SN+ANDROID_ID+BRAND_INFO, 再统一HASH_CODE格式,生成设备ID,在手机SD卡中新建隐藏文件进行存储,再次进入时如果有,则使用之前的,没有则生成新的(生成新的ID的关键因子不变,则生成的新ID也不会改变)。
4. 关键代码:
获取序列号:
private static String
getSerialId() {
String androidSerialId = null;
try {
//
try to get device serial number
androidSerialId
= Build.SERIAL;
} catch (NoSuchFieldError ignored) {
}
return
androidSerialId;
}
获取ANDROID_ID:
private static String getAndroidId(Context context) {
String androidId = null;
String androidSecureId = Settings.Secure.getString(context.getContentResolver(), Settings.Secure.ANDROID_ID);
if (!TextUtils.isEmpty(androidSecureId) && !EMULATOR_ANDROID_ID.equals(androidSecureId) && !isBadDeviceId(androidSecureId)
&& androidSecureId.length() == EMULATOR_ANDROID_ID.length()) {
androidId = androidSecureId;
}
return androidId;
}
获取手机关键字:
private static String getZacBrandId() {
return Build.BOARD
+ Build.BRAND
+ Build.CPU_ABI
+ Build.DEVICE
+ Build.MANUFACTURER
+ Build.MODEL
+ Build.PRODUCT;
}
最终生成设备ID号:
public static String readDeviceId(Context context) {
String id1 = getSerialId();
String id2 = getAndroidId(context);
String id3 = getZacBrandId();
String id;
if(TextUtils.isEmpty(id1) && TextUtils.isEmpty(id2)) {
id = SoftInstallationId.id(context) + id3;
} else {
id = id1 + id2 + id3;
}
return new UUID(id.hashCode(), id3.hashCode()).toString();
}
浙公网安备 33010602011771号