ios获取手机唯一标识符(标识符的详细使用)

想要追踪、统计用户,自然离不开用户唯一标识符,这是每个公司都面临的问题。在历史上唯一标识符很多,如UDID、MAC地址、OpenUDID等,不再一一介绍他们是怎么挂掉的,现在好用的只剩下了idfa、idfv、UUID+keyChain。

在2013年3月21日苹果已经通知开发者,从2013年5月1日起,访问UIDID的应用将不再能通过审核,替代的方案是开发者应该使用“在iOS 6中介绍的Vendor或Advertising标示符”。unique Identifier即将退出,苹果给了我们Vendor和Advertising identifier两个选择,但应该用哪一个?文档并没有给出确切答案,具体使用哪个完全由你根据自己app的目的来决定。下面我将列出iOS中目前支持的,以及被废弃的唯一标示符方法,并对其做出相应的解释,希望可以帮你做出正确的确定。

一、推荐使用的方法

1.1、广告标示符(IDFA-identifierForIdentifier):

可以理解为广告id,apple公司提供的用于追踪用户的广告标识符。

使用了IDFA的在提交app的时候需要注意:appstore中关于IDFA的选项和设置

缺点:如果用户完全重置系统((设置程序 -> 通用 -> 还原 -> 还原位置与隐私) ,这个广告标示符会重新生成。

另外如果用户明确的还原广告(设置程序-> 通用 -> 关于本机 -> 广告 -> 还原广告标示符) ,那么广告标示符也会重新生成。

要求:iOS>=6.0

这是iOS 6中另外一个新的方法,advertisingIdentifier是新框架AdSupport.framework的一部分。ASIdentifierManager单例提供了一个方法advertisingIdentifier,通过调用该方法会返回一个上面提到的NSUUID实例。

//需要导入AdSupport.framework这个库
#import <AdSupport/AdSupport.h>
NSString *idfa = [[[ASIdentifierManager sharedManager] advertisingIdentifier] UUIDString];

跟CFUUID和NSUUID不一样,广告标示符是由系统存储着的。不过即使这是由系统存储的,但是有几种情况下,会重新生成广告标示符。

关于广告标示符的还原,有一点需要注意:如果程序在后台运行,此时用户“还原广告标示符”,然后再回到程序中,此时获取广告标示符并不会立即获得还原后的标示符。必须要终止程序,然后再重新启动程序,才能获得还原后的广告标示符。之所以会这样,我猜测是由于ASIdentifierManager是一个单例。

针对广告标示符用户有一个可控的开关“限制广告跟踪”。

// 判断是否开启  限制广告跟踪选项(该选项在设置-隐私-广告-限制广告隐私)
Boolean on = [[ASIdentifierManager sharedManager] isAdvertisingTrackingEnabled];

Nick Arnott的文章中已经指出了。将这个开关打开,实际上什么也没有做,不过这是希望限制你访问广告标示符,ios10之前开关限制广告追踪选项的确没什么用,ios10之后,如果手机开启限制广告追踪的话就不能再得到广告标识符,得到的是下面的0。这个开关是一个简单的boolean标志,当将广告标示符发到任意的服务器端时,你最好判断一下这个值,然后再做决定。

NSLog(@"%@\n",[[[ASIdentifierManager sharedManager] advertisingIdentifier]UUIDString]);
NSLog(@"%d\n",[[ASIdentifierManager sharedManager] isAdvertisingTrackingEnabled]);

输出时,当手机的限制广告追踪开启的时候

//开启的时候
2016-01-05 15:22:19.218 sss[1773:60b] 41B2FD07-695A-4A27-8D26-C30ECE6F7EAD
2016-01-05 15:22:19.233 sss[1773:60b] 0

关闭的时候是

//关闭的时候
2016-01-05 15:19:57.502 sss[1763:60b] 7773E145-26FF-4304-A60F-60C948D52B40
2016-01-05 15:19:57.516 sss[1763:60b] 1

开启和关闭切换的话,idfa会变,如果不切换,保持开启状态,每次都是不会变的,当切换了下之后就会变,或者还原的话会变

ios10更新:

ios10之后,当打开限制广告追踪的时候虽然在模拟器上面仍能获得,但是真机调试,如果手机开启限制广告追踪的话就不能再得到广告标识符,得到的是下面的0,所以ios10之后也推荐使用后面说的SimulateIDFA

00000000-0000-0000-0000-000000000000

1.2、idfv (identifierForVendor)

apple提供给Vendor的唯一标识符,Vendor代表了应用开发商,实际使用时,一个Vendor是CFBundleIdentifier的前两部分。例如,com.baidu.tieba 和 com.baidu.image 得到的idfv是相同的,因为它们的CFBundleIdentifier 前两部分是相同的。

优点:当开关限制广告追踪的选项时,idfv不会改变

缺点:把同一个开发商的所有应用卸载后,再次安装取到的idfv会不同,如果只有你这一个软件,卸载之后重新安装idfv会变化。

要求:iOS>=6.0

NSString *idfv = [[[UIDevice currentDevice] identifierForVendor] UUIDString];

示例

//关闭广告追踪限制
2016-10-15 22:26:24.635363 test[1219:425254] idfa:22EDE0F9-9088-40DB-BFBD-1BC6F1E37C71
2016-10-15 22:26:24.636190 test[1219:425254] idfv:06C58C45-823F-48B0-B906-0ACC9925D070
//开启广告追踪限制
2016-10-15 22:27:36.337051 test[1226:426248] idfa:00000000-0000-0000-0000-000000000000
2016-10-15 22:27:36.337459 test[1226:426248] idfv:06C58C45-823F-48B0-B906-0ACC9925D070
//开启广告追踪限制,重新安装软件
2016-10-15 22:28:08.265168 test[1228:426658] idfa:00000000-0000-0000-0000-000000000000
2016-10-15 22:28:08.265559 test[1228:426658] idfv:5A07C951-A62C-495D-98CE-C7EDE3CEE064

1.3、NSUUID(每次调用都会改变)

NSUUID在iOS 6中才出现,这跟CFUUID几乎完全一样,只不过它是Objective-C接口。+ (id)UUID 是一个类方法,调用该方法可以获得一个UUID。通过下面的代码可以获得一个UUID字符串:

NSString *uuid = [[NSUUID UUID] UUIDString];

跟CFUUID一样,这个值系统也不会存储,每次调用的时候都会获得一个新的唯一标示符。如果要存储的话,你需要自己存储。在我读取NSUUID时,注意到获取到的这个值跟CFUUID完全一样(不过也可能不一样):

示例: 68753A44-4D6F-1226-9C60-0050E4C00067

1.4、SimulateIDFA

SimulateIDFA是解决ios10之后,如果开启广告限制就追踪不到idfa的问题,SimulateIDFA 是根据一堆设备信息(每个app获取的值都是一样的)生成的一个MD5值。用于标志不同设备。生成的MD5值分两部分。

以 626363D0-90D4-06BF-C281-384E4E69D3E2 为例:

前16位626363D0-90D4-06BF是由比较稳定的参数组合获得,这前16位只有在系统升级的情况下才会变。

后16位C281-384E4E69D3E2 由 一些比较容易被改变的参数组合生成,比较常见的值变化情况是系统重新启动。

参与前16位计算的参数有:

系统版本(9.3.2)、硬件信息(N53AP,iPhone6,2,中国移动46002,1048576000)、coreServices文件创建更新时间(2015-08-07 23:53:00 +0000,2016-06-07 23:53:09 +0000),系统容量(12266725376)

这里有一些信息是升级的时候会变的,系统版本、coreServices文件创建更新时间、系统容量

参与后16位计算的参数有:

系统开机时间(1473301191去掉后面的4位数 147330)、国家代码(CN)、本地语言(zh-Hans-CN)、设备名称(XXXX)

这里的参数都是比较容易变化的,系统重启离上次重启有10000秒的话会变,其他参数在设置里面可以修改

优点:解决了IOS10开启广告限制就追踪不到idfa的问题

缺点:SimulateIDFA分两部分,前16位是在系统升级的时候才会变化,后16位用户的某些行为可能会导致值变化(例如:重启手机、修改设备名称、修改手机本地语言),意思就是系统升级,修改设备名称等都会改变

github下载地址:https://github.com/youmi/SimulateIDFA

从github下载源码,把头文件SimulateIDFA.h和SimulateIDFA.m引入工程

#import "SimulateIDFA.h"
NSString *simulateIdfa =[SimulateIDFA createSimulateIDFA];
NSLog(@"simulateIdfa:%@",simulateIdfa);

得到的结果

//关闭广告限制
2016-10-15 22:49:39.682863 SimulateIDFADemo[1242:433288] simulateIdfa:4E91FF42-F7D9-C74D-1CF7-84CB337BD11B
//开启广告限制
2016-10-15 22:50:19.374259 SimulateIDFADemo[1247:433975] simulateIdfa:4E91FF42-F7D9-C74D-1CF7-84CB337BD11B
//重装软件
2016-10-15 22:50:47.091237 SimulateIDFADemo[1249:434374] simulateIdfa:4E91FF42-F7D9-C74D-1CF7-84CB337BD11B
//修改手机名称
2016-10-15 22:59:24.077596 SimulateIDFADemo[1267:437081] simulateIdfa:4E91FF42-F7D9-C74D-D12F-A210F3E747E8
//修改手机语言
2016-10-15 23:01:25.405772 SimulateIDFADemo[1316:439169] simulateIdfa:4E91FF42-F7D9-C74D-4E4A-67F36D496162

二、被弃用的方法

2.1、CFUUID(每次都会改变)

从iOS2.0开始,CFUUID就已经出现了。它是CoreFoundatio包的一部分,因此API属于C语言风格。CFUUIDCreate 方法用来创建CFUUIDRef,并且可以获得一个相应的NSString,如下代码:

CFUUIDRef cfuuid = CFUUIDCreate(kCFAllocatorDefault);NSString *cfuuidString = (NSString*)CFBridgingRelease(CFUUIDCreateString(kCFAllocatorDefault, cfuuid));

获得的这个CFUUID值系统并没有存储。每次调用CFUUIDCreate,系统都会返回一个新的唯一标示符。如果你希望存储这个标示符,那么需要自己将其存储到NSUserDefaults, Keychain, Pasteboard或其它地方。

2.2、UDID(该函数已经被移除)

在之前的版本中是可用的,但是在iOS5以及之后的版本中,以及被弃用了。虽然,这个UDID用得很广泛,但是,不得不说的是,它在慢慢的远离开发者,不能在考虑使用UDID了。至于这个标示符是转为私有方法,或者完全从以后的iOS版本中移除,还有待观察。不过,这个UDID在部署企业级签名程序时,非常方便。获取UDID的方法如下:

NSString *udid = [[UIDevice currentDevice] uniqueIdentifier];

示例: bb4d786633053a0b9c0da20d54ea7e38e8776da4

2.3、OpenUDID(在ios7以上已经作废)

在iOS 5发布时,uniqueIdentifier被弃用了,这引起了广大开发者需要寻找一个可以替代UDID,并且不受苹果控制的方案。由此OpenUDID成为了当时使用最广泛的开源UDID替代方案。OpenUDID在工程中实现起来非常简单,并且还支持一系列的广告提供商。

NSString *openUDID = [OpenUDID value];

OpenUDID利用了一个非常巧妙的方法在不同程序间存储标示符 — 在粘贴板中用了一个特殊的名称来存储标示符。通过这种方法,别的程序(同样使用了OpenUDID)知道去什么地方获取已经生成的标示符(而不用再生成一个新的)。

之前已经提到过,在将来,苹果将开始强制使用advertisingIdentifier 或identifierForVendor。如果这一天到来的话,即使OpenUDID看起来是非常不错的选择,但是你可能不得不过渡到苹果推出的方法。

示例: 0d943976b24c85900c764dd9f75ce054dc5986ff

2.4、MAC+MD5获取(ios7之后已经作废)

从iOS7开始,获取MAC地址的方法统一返回02:00:00:00:00:00,所以使用MAC+MD5方法已无意义

三、持久化保存状态

因为一直不变的UDID已经被苹果移除,所有标志符是会因为操作改变的,这里总结下用户操作手机是否会修改保存状态,值是否会变,

√表示值不会变,×标识值会变,?表示未测试


启动程序后台返回重置广告标志符重新安装程序重启手机系统还原升级系统重装系统
UDID(已作废)
mac+md5(已作废)

CFUUID

××××××××
NSUUID××××××××
IDFA×××
IDFV××√(?)×
OpenUDID(已作废)××
SecureUDID×××
SimulateIDFA××××

四、总结

SecureUDID是一个第三方库,是一个开源的基于沙箱机制的解决方案,是虚拟出来的,所以不能确保不同设备上的UDID不同,用户可以选择阻止SecureUDID收集UDID信息,如果用户备份A设备系统并将其恢复到B设备,则B设备将得到A设备的UDID,删除程序并清空剪切板可能会导致丢失,非苹果原生的API,所以使用的话还是最好使用idfa和idfv。

idfa在用户重置广告标志符的时候会变化,所以可以把第一次生成的idfa存放到keychain里面,以后就直接读取keychain值就可以了,这样就能避免用户重置广告标志符造成idfa的变化,而keychain的值只有在用户重置系统的时候才会删除,所以很适合用idfa+keychain的方案,keychain的使用方法《IOS的keychain的三种使用方法

五、参考文章

Last modification:January 1st, 1970 at 08:00 am
如果看了这个文章可以让你少加会班,可以请我喝杯可乐
已打赏名单
微信公众号

Leave a Comment