iOS设备唯一标识符

开发中需要获取设备的唯一标识符,以便用于应用统计或者产品的推广,这是很常见的开发需求。然而很遗憾,傲娇的苹果很是注重用户的隐私保护,随着系统的升级,各种能够获取设备标识符的方法要不被禁止了,要不就是很多限制条件。

获取设备标识符的血泪历程

UDID(Unique Device Identifier)

上古时代的方法,iOS5之前可以支持。

MAC Address

MAC地址在网络上用来区分设备的唯一性,所以可以用来作为设备的唯一标识符,但在iOS7之后,请求Mac地址都只会得到一个固定值,所以该方法也废了。

UUID(Universally Unique Identifier)

可生成应用唯一标识字符串,但在用户删除重装应用时,会生成新的字符串,所以不能保证唯一识别该设备。

apple push token

依赖于APNS,而且苹果push有时会抽风,该方法不可取。

IDFA(advertisingIdentifier)

广告id,苹果专门给各广告提供商用来追踪用户而设的,有几种情况下会重置:1、用户完全重置系统(设置程序 -> 通用 -> 还原 -> 还原位置与隐私),2、还原广告(设置程序-> 通用 -> 关于本机 -> 广告 -> 还原广告标示符) 。而且还有一点:如果程序在后台运行,此时用户“还原广告标示符”,然后再回到程序中,此时获取广 告标示符并不会立即获得还原后的标示符。必须要终止程序,然后再重新启动程序,才能获得还原后的广告标示符。另外使用了IDFA的应用提交审核时,必须要有广告存在,不然被拒是必然的。所以该方法也不可取。

IDFV(identifierForVendor)

Vindor标示符,每个设备在所属同一个Vender的应用里,都有相同的值。其中的Vender是指应用提供商,但准确点说,是通过BundleID的DNS反转的前两部分进行匹配,如果相同就是同一个Vender,例如对于:com.company.appA,com.company.appB,就属于同一个Vender,共享同一个idfv的值。idfv的值是一定能取到的,适合于作为内部用户行为分析的主id,来标识用户。但如果用户将属于此Vender的所有App卸载,则idfv的值会被重置。IDFV也不可取。

OpenUDID

每台iOS设备的OpenUDID是通过第一个带有OpenUDID SDK包的App生成,如果完全删除全部带有OpenUDID SDK包的App(比如恢复系统等),OpenUDID会重置,这个方法也不保险。

可行的解决方案

iOS获取设备唯一标识符的一种可行的解决方案:是通过KeyChain来保存生成的设备唯一标识符,这样不管是在应用删除重装,或者是系统升级时,都能够保证标识的唯一性。
下面是我在开发中封装的一个获取设备标识符的库keychainDeviceID
类中包含三个方法:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
/**
* 获取UUID作为设备唯一标志符
*
* @return
*/
+ (NSString *)getUUID;

/**
* 获取OpenUDID作为设备唯一标志符
*
* @return
*/
+ (NSString *)getOpenUDID;

/**
* 从keychain删除DeviceID,一般不会用到
*/
+ (void)deleteDeviceID;

调用getUUIDgetOpenUDID会从KeyChain中读取对应的标识符,如果是初次读取,则会先生成标识符存入KeyChain再返回。deleteDeviceID 是删除标识符,很少情况会使用到。

库的引用:
下载CJKeychainDeviceID Demo,将keychainDeviceID文件夹引用到项目中即可,代码示例:

1
2
3
4
#import "keychainDeviceID.h"

NSString *UUID = [keychainDeviceID getUUID];
NSString *openUDID = [keychainDeviceID getOpenUDID];