手机唯一标识生成方案

首先,就目前掌握的资料来看,该问题没有彻底的解决方案。网络资料很多,主要分为4类。建议采用方案4。

 

方案一:Android设备标识或设备硬件信息

常用的有:

1)蓝牙/Wifi的Mac地址、IMSI、sim卡序列号;

2)CPU 的名称、核数、频率,Ram大小、Rom大小、屏幕分辨率,CPU的序列号在目前的测试设备中,显示为一串0;

3)device_id、android_id、serialno。

 

首先,有些在Android低版本(2.1到2.3)不稳定。其次,上面的几类各有缺点:

第1类受用户行为影响较大,比如开关wifi或蓝牙,插拔sim卡;

第2类表征能力差,同一型号手机中,这些特点没有区分度;

第3类是推荐的,但不能抵抗wipe,其中android_id的生成是以serialno为基础的。

方案二:采用UUID跟踪特定安装,不必绑定具体的设备

随机生成UUID,在本地存储。不做赘述。详见:

http://android-developers.blogspot.co.uk/2011/03/identifying-app-installations.html

 

方案三:Android Backup Service

AndroidBackup Service provides a backup transport for Android's data backup framework,which allows you to copy a user's persistent app data to remote "cloud" storage. 未做深入研究。

详见:

http://developer.android.com/training/cloudsync/backupapi.html

https://developer.android.com/google/play-services/auth.html

 

方案四:方案1和方案2的结合

这种方法是,以一些特定的信息为基础,生成设备的唯一标识。

首先,算法角度,常用的有UUID、摘要两种。这两种算法都是以特定的数据为基础,生成一个唯一的、固定长度的字符串。这里选择UUID。

 

其次,计算的基础数据,建议选择divice_id和android_id。原因是,1)这两个标识虽然不能抵抗wipe操作,但受用户的行为影响比较小;2)如果正常获取,都是唯一的;③如果不能正常获取,结果也是固定的,不会频繁变化。

 

再次,优先级的考虑。从这两个标识的缺点考虑。

1)device_id。

①不能标识非手机设备,例如Pad。

②权限问题,因为用户的反感。

③获取异常,厂商定制系统中存在的bug,致使返回结果为空,或者为一串“0”或“*”。

④对于双卡双待手机,会返回两个device_id。

2)android_id。

①Android2.3以前,系统Bug,导致不同的设备产生相同的结果:9774d56d682e549c。

②有些可能返回null。

③设备差异:对于CDMA设备,与device_id返回相同的值。

综合考虑,device_id不能标识某些pad,以及用户的权限问题,是我们不能接受的,所以优先使用android_id。对于android_id返回为null的情况,再考虑使用device_id。

 

最后,当android_id和device_id都返回异常的情况,我们可以随机生成一个UUID。

 

关于android_id的生成机制见参考资料:

http://my.oschina.net/u/996206/blog/215960

 

主要代码

主要代码如下,详见Demo程序。

    private String getUUID(){

        UUID uuid;

        String androidId = android_id;

        try {

            if(!"9774d56d682e549c".equals(androidId)) { 

//Android2.3版本之前才会有这个问题。

                uuid = UUID.nameUUIDFromBytes(androidId.getBytes("utf8"));

            } else {

                String deviceId = device_id;

                uuid = deviceId != null ?UUID.nameUUIDFromBytes(deviceId.getBytes("utf8")) :UUID.randomUUID();

            }

        } catch (UnsupportedEncodingExceptione) {

            throw new RuntimeException(e);

        }

        return uuid.toString();

    }

 

测试结果

根据在现有测试机上的测试结果,android_id可以正常获取到,所以生成的UUID都是以此为基础的。

 

以下是测试结果数据。

 

手机型号:GT-I9300I

android_id:c3bec6b0ed7cbc20

device_id:359776058450570

andr_uuidf205bf07-ee2f-3d27-b3ff-c8db52bed45c

dev_uuid:915c5b80-2368-3fa4-85aa-c1316d852be2

UUIDf205bf07-ee2f-3d27-b3ff-c8db52bed45c

 

 

手机型号:HONORH30-L01

android_id:4e5d03bca1d55673

device_id:864502020279410

andr_uuid89101b66-2d8a-3f82-8bc2-cfba09edff7c

dev_uuid:0fc0f0d0-0b82-3476-a674-0e285427c650

UUID89101b66-2d8a-3f82-8bc2-cfba09edff7c

 

 

手机型号:vivoS7i(t)

android_id:b0374e0856f27689

device_id:863880029053270

andr_uuid1cf7fb3f-f836-3510-9fe2-ee08cd9b1cd2

dev_uuid:34053b22-f29b-3039-a593-23f534a0207c

UUID1cf7fb3f-f836-3510-9fe2-ee08cd9b1cd2

 

 

手机型号:GT-S7572

android_id:c09ff3a16a57e6bc

device_id:358905059907129

andr_uuidda400450-c131-3399-be5e-facfc0866ceb

dev_uuid:077c827d-96c6-3d4f-b508-283c1cdd6e0f

UUIDda400450-c131-3399-be5e-facfc0866ceb

 

 

手机型号:HUAWEIY320-T00

android_id:4d40a1dfa74973c5

device_id:860271022990473

andr_uuid77fe6e20-5afe-37ec-b916-f11be3b9dbf5

dev_uuid:e6ef768a-9398-33aa-a925-15c7696deef5

UUID77fe6e20-5afe-37ec-b916-f11be3b9dbf5

 

 

手机型号:HTCSensation XE with Beats Audio Z715e

android_id:c5dc41f5caabe5d2

device_id:358313045847881

andr_uuide282e4f1-70ed-3d95-af5b-ebdfd2c90a28

dev_uuid:133095a2-0f3e-325b-ada5-b486fb351e0a

UUIDe282e4f1-70ed-3d95-af5b-ebdfd2c90a28

 

不足之处与改进

就目前的调研结果,对android_id饱受诟病的地方是,wipe之后会变化或者无法得到正常返回。device_id在wipe之后,有说有影响的,有说不变化的。

 

再考虑到device_id的权限申请问题、不能标识非手机的移动设备等问题,建议只用android_id即可,如果android_id不能正常返回,则随机生成一个。

 

最后,选择android_id与device_id而非其它的硬件信息的原因已经在方案一中提到。虽然android_id是基于serialno生成,而后者也是一种硬件信息,但这受wipe的影响,并不是不变的。

 

如果坚持要从硬件角度唯一的标识设备,恐怕还要从wifi与蓝牙mac地址等角度考虑,而这受用户的行为影响较大。比如,注册时同时取得mac与sim卡序列号,根据两者确定一个准则;后续对设备的确定方法,在wifi下采用mac,在2G/3G下根据sim序列号。


版权声明:本文为GoneWithFate原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明。