iOS设备标识演进

       随着iOS系统版本的演进,或是出于安全的角度,或是出于保护用于隐私的需求,iOS设备获取设备唯一标识的方法也在不断地发生变化。 一些公认的设备标识,比如UDID或MAC地址,虽然我们可以通过iTunes等工具查看联机设备的具体参数,但目前已经无法通过合法的系统API获取到这些参数。
       因此,如何基于不同iOS版本获取正确的设备标识,对于一个iOS开发人员来讲,是一个特别需要注意的问题。
       首先,先对iOS的那一揽子设备标识作一个全面的梳理和总结。

一、UDID
        UDID的全称是Unique Device Identifier,其实从一开始就是苹果IOS设备的唯一识别码。UDID由40个字符的字母和数字组成。
        iOS5.0以前,系统为我们提供了下面的API获取UDID:
[UIDevice currentDevice] uniqueIdentifier]

        但是,从IOS5.0(2011年8月份)开始,苹果宣布将不再支持用uniqueIdentifier方法获取设备的UDID。进一步苹果官方于2013年3月21日苹果已经通知开发者:从2013年5月1日起,访问UIDID的程序将不再被审核通过。也就是说,即使iOS5.0以下的版本,只要iOS使用了相关的API,那么该应用程序基本无法审核通过。
       目前,UDID可以通过将iOS设备连接电脑,从iTunes中看到。主要用于在开发、测试过程中,需要将iOS设备的udid添加到苹果开发者帐号的Registered Devices以明确设备的合法性。

二、UUID
        UUID全称Universally Unique Identifier,中文意思是通用唯一识别码.
        简单来说,UUID就是一个随机序列字符串生成器,有点像Microsoft Windows的COM GUID生成器的作用,比起自己随机一个字符串的好处就是这东西能够保证唯一性,适用于标记。
        相关的调用方法随着iOS系统的不同,分为两种:
        1,CFUUID
        从iOS2.0开始,CFUUID就已经出现了。它是CoreFoundatio包的一部分,因此API属于C语言风格。CFUUIDCreate 方法用来创建CFUUIDRef,并且可以获得一个相应的NSString。具体实现,如下代码:
CFUUIDRef cfuuid = CFUUIDCreate(kCFAllocatorDefault);
NSString *cfuuidString (NSString*)CFBridgingRelease(CFUUIDCreateString(kCFAllocatorDefault, cfuuid));

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

        需要注意的是,获得的这个CFUUID值系统并没有存储。每次调用CFUUIDCreate,系统都会返回一个新的唯一标示符。如果你希望存储这个标示符,那么需要自己将其存储到NSUserDefaults, Keychain, Pasteboard或其它地方。
        从UUID的生成原理,不难看出,UUID最多只能唯一标识自己的应用,涉及到和第三方app的合作,将不再适用。

三、MAC地址(hash值)
        毫无疑义,MAC地址是一个唯一的号码,它是物理网络层级方面分配给网络适配器的。这个地址苹果还有其他的名字,比如说是硬件地址(Hardware Address)或是Wifi地址,都是指同样的东西。
        在UDID失效之后,曾经有很多工程和框架都使用这个方法来生成唯一的设备ID。比如说ODIN。
        但是,iOS7系统发布之后,苹果明确禁止开发者获取MAC地址。现在,如果你在iOS7和iOS8系统上查询MAC地址,它都返回同样的数值02:00:00:00:00:00。因此这里要特别提醒下iOS7以前就已经开始开发的iOS app,如果还在用MAC地址,赶紧修改。

四、Vindor ID
        Vindor标示符 (IDFV-identifierForVendor)
        这种叫法也是在iOS 6中新增的,不过获取这个IDFV的新方法被添加在已有的UIDevice类中。调用方法如下:
NSString *idfv = [[[UIDevice currentDevice] identifierForVendor] UUIDString];

        苹果官方的文档中对identifierForVendor有如下这样的一段描述 :
  • The value of this property is the same for apps that come from the same vendor running on the same device. A different value is returned for apps on the same device that come from different vendors, and for apps on different devices regardless of vendor.

        大概的意识是如果满足这样的条件,那么获取到的这个属性值就不会变:相同的一个程序里面-相同的vindor-相同的设备。
        如果是这样的情况,那么这个值是不会相同的:相同的程序-相同的设备-不同的vindor,或者是相同的程序-不同的设备-无论是否相同的vindor。
        一个疑问“vendor是什么”?实际上Vendor就是CFBundleIdentifier(反转DNS格式)的前两部分。例如,com.doubleencore.app1 和 com.doubleencore.app2 得到的identifierForVendor是相同的,因为它们的CFBundleIdentifier 前两部分是相同的。不过这样获得的identifierForVendor则完全不同:com.massivelyoverrated 或 net.doubleencore。
如果用户卸载了同一个vendor对应的所有程序,然后在重新安装同一个vendor提供的程序,此时identifierForVendor会被重置。

五、IDFA
        IDFA全称:广告标示符(IDFA-identifierForIdentifier)
        IDFA也是iOS 6中另外一个新的方法,advertisingIdentifier是新框架AdSupport.framework的一部分。ASIdentifierManager单例提供了一个方法advertisingIdentifier,通过调用该方法会返回一个上面提到的NSUUID实例。
NSString *adId = [[[ASIdentifierManager sharedManager] advertisingIdentifier] UUIDString];

        但是和UDID以及Vindor ID不同的是,广告标示符是由系统存储着的。
        而且只有在几种极端的场景下,广告标示符的值才会发生变化。
        1,用户完全重置系统((设置程序 ->通用 ->还原 ->还原位置与隐私) ,这个广告标示符会重新生成。
        2,用户明确的还原广告(设置程序->通用 ->关于本机 ->广告 ->还原广告标示符) ,那么广告标示符也会重新生成。后面这一项,在iOS8上已经没有了。
        从IDFA的特性不难发现:
  • IDFA的值是和设备绑定的,也就是说同一台iOS设备上,不同的应用app获取的IDFA的值是一样的。
  • 即使用户卸载了某个应用,重新安装应用后,IDFA的值也不会发生改变。
  • 只有重置系统才会导致IDFA的改变,但是重置系统首先会抹掉所有APP应用,因此即使改变,也属可接受范畴。

六、Open UDID
        前面几个标识,都是通过苹果官方提供的标识方案。而Open UDID则是一个开源的方案。
        在iOS 5发布时,uniqueIdentifier被弃用了,这引起了广大开发者需要寻找一个可以替代UDID,并且不受苹果控制的方案。由此OpenUDID成为了当时使用最广泛的开源UDID替代方案。OpenUDID在工程中实现起来非常简单,并且还支持一系列的广告提供商。我们只需引入先关的源码文件,执行下面的调佣即可:
NSString *openUDID = [OpenUDID value];

        简单来说,OpenUDID利用了一个非常巧妙的方法在不同程序间存储标示符 — 在粘贴板中用了一个特殊的名称来存储标示符。通过这种方法,别的程序(同样使用了OpenUDID)知道去什么地方获取已经生成的标示符(而不用再生成一个新的)。只要用户设备上有一个使用了OpenUDID的应用存在时,其他后续安装的应用如果获取OpenUDID,都将会获得第一个应用生成的那个。
        但是根据贡献者的代码和方法,和一些开发者的经验,如果把使用了OpenUDID方案的应用全部都删除,再重新获取OpenUDID,此时的OpenUDID就跟以前的不一样。

总结:
不同设备标识符方法的iOS版本适用性
适用性 iOS4 iOS5 iOS6 iOS7 iOS8 iOS9
UDID 支持 过期 过期 过期 过期 过期
UUID 支持 支持 支持 支持 支持 支持
MAC地址 支持 支持 支持 过期 过期 过期
Vindor ID 不支持 不支持 支持 支持 支持 支持
IDFA 不支持 不支持 支持 支持 支持 支持
OpenUDID 支持 支持 支持 支持 支持 支持


不同设备标识符方法的持久性
是否保持不变 app重启 app卸载重装 系统重启 还原位置与隐私 系统重置
UDID
UUID
MAC地址
Vindor ID 否(最后一个vendor)
IDFA
OpenUDID 否(最后一个支持OpenUDID)


设备标识符的作用
应用级别,统计应用的活跃量、应用特性参数等app特有的信息。
设备级别,比如统计广告的推广效果,自己的应用必须和第三方推广商使用一致的设备标识。

推荐客户端的使用的iOS标识策略
经常性的和多盟等第三方广告公司合作,设备唯一标识应该遵循业内的通用做法。
推荐使用IDFA作为设备标识。

猜你喜欢

转载自kmplayer.iteye.com/blog/2323188
今日推荐