19非Ad应用,模拟获取设备的 idfa

2017-06-22  本文已影响695人  i爱吃土豆的猫

0前言

像 UUID、UDID、IDFV, 这些比较老的唯一标识, 苹果早已经对外关闭,开发者是拿不到的, 详情不赘述
开发的过程中, 需要拿到设备的唯一标识或者是用户登录的唯一标识, 还是很重要的, 因为服务端会根据你的这个唯一的东西, 给你生成唯一的账号或者标识, 包括后续的"追踪定位"、进程异常、日志查询等, 都会很有很大的帮助

1.KeyChain

简介:iOS整个系统有一个KeyChain,每个程序都可以往KeyChain中记录数据,而且只能读取到自己程序记录在KeyChain中的数据。而且就算我们程序删除掉,系统经过升级以后再安装回来,依旧可以获取到与之前一致的UDID(系统还原、刷机除外)。因此我们可以将UUID的字符串存储到KeyChain中,然后下次直接从KeyChain获取UUID字符串。(本示例中使用KeychainItemWrapper工具类)

获取
+ (NSString *)UUID {
KeychainItemWrapper *keyChainWrapper =
[[KeychainItemWrapper alloc] initWithIdentifier:@"MYAppID" accessGroup:@"com.test.app"];
NSString *UUID = [keyChainWrapper objectForKey:(__bridge id)kSecValueData];

    if (UUID == nil || UUID.length == 0) {
    UUID = [[[UIDevice currentDevice] identifierForVendor] UUIDString];
    [keyChainWrapper setObject:UUID forKey:(__bridge id)kSecValueData];
}

     return UUID;
}

2.AppleAccount

简介:虽然苹果在iOS6中禁用了获取uuid的方式,但是只要你研究下就知道这个API只是私有化了,使用私有API还是可以获取设备的uuid。但是这个方面也面临着风险:比如API变更使用以及AppStore审核问题,导致上架不了或者下架
但是在越狱设备上你还是可以尽情享用的

类:AADeviceInfo(dump出头文件)

@class NSObject<OS_dispatch_semaphore>, APSConnection, NSData;

@interface AADeviceInfo : NSObject {

APSConnection *_apsConnection;

BOOL _tokenDone;

NSData *_token;

NSObject<OS_dispatch_semaphore> *_tokenSema;

}

+ (id)userAgentHeader;

+ (id)signatureWithDictionary:(id)arg1;

+ (id)apnsToken;

+ (id)serialNumber;

+ (id)clientInfoHeader;

+ (id)appleIDClientIdentifier;

+ (id)productVersion;

+ (id)osVersion;

+ (id)udid;

+ (id)infoDictionary;

- (id)wifiMacAddress;

- (id)regionCode;

- (id)deviceClass;

- (id)osName;

- (id)productType;

- (id)apnsToken;

- (id)serialNumber;

- (id)deviceInfoDictionary;

- (id)appleIDClientIdentifier;

- (id)productVersion;

- (id)osVersion;

- (id)udid;

- (id)init;

- (void).cxx_destruct;

- (id)buildVersion;

@end

获取:

[AADeviceInfo udid]

使用方法:在项目中将真机上的AppleAccount.framework框架导出,引入Xcode工程中,利用runtime或者直接使用该类就行。
(细节补充:导出AppleAccount.framework后,进入AppleAccount.framework的根目录,新建Headers文件夹,然后将dump出的头文件放在Headers目录,就可以像引用第三方framework一样在项目中使用)

3.IDFA

简介:广告标示符,适用于对外:例如广告推广,换量等跨应用的用户追踪等。但如果用户完全重置系统((设置程序 -> 通用 -> 还原 -> 还原位置与隐私) ,这个广告标示符会重新生成。另外如果用户明确的还原广告(设置程序-> 通用 -> 关于本机 -> 广告 -> 还原广告标示符) ,那么广告标示符也会重新生成。
注意:如果程序在后台运行,此时用户“还原广告标示符”,然后再回到程序中,此时获取广 告标示符并不会立即获得还原后的标示符。必须要终止程序,然后再重新启动程序,才能获得还原后的广告标示符。在同一个设备上的所有App都会取到相同的值,是苹果专门给各广告提供商用来追踪用户而设的,
用户可以在 设置 -> 隐私 -> 广告追踪 里重置此id的值,或限制此id的使用。

获取:

[[[ASIdentifierManager sharedManager] advertisingIdentifier] UUIDString];

适用:iOS6.0+

例子:9C287922-EE26-4501-94B5-DDE6F83E1475

4.IDFA 的前世今生

为了保护用户隐私,早在2012年就不再允许其生态中的玩家获取用户的唯一标识符,但是商家在移动端打广告的时候又希望能监控到每一次广告投放的效果,因此,苹果想出了折中的办法,就是提供另外一套和硬件无关的标识符,用于给商家监测广告效果,同时用户可以在设置里改变这串字符,导致商家没有办法长期跟踪用户行为。这个就叫做广告标识符(IDFA),设置路径是“设置->隐私->广告->还原广告标识符”,如下图所示(iOS9)

image.png

因为这个IDFA不是唯一的,所以一开始行业内是很抵触的,想方设法去获取UDID(跟手机绑定的,用户不能改变),引起苹果大怒,在13年时禁止所有App获取UDID,否则不能上架,也正因为其生态的封闭性,才能迫使大家就范。虽然IDFA不是唯一的,但是毕竟胜过没有,况且也没有多少用户会去更改。因此,经过几番争斗,IDFA已经成为通用的iPhone用户标识符,这个过程分为6个阶段,我用下图总结

image.png

然而在今年iOS10推出后,广告界大为震惊,因为苹果推出了“限制广告追踪”功能,设置的路径和iOS9一致。可能细心的人注意到了,这个功能并非iOS10独有啊,在之前的版本中也一样存在。不过经过实际的测试,在iOS10之前,即使用户打开这个功能,商家一样可以获取IDFA,只不过与之前的不一样了,每次切换这个开关与点击“还原广告标识符”的效果一样。而iOS10就不一样了,当用户打开这个功能后,商家只能获取到一连串无意义的0,这才是广告界大为震惊的原因所在

image.png

5. iOS10获取idfa的坑

iOS10更新之后一旦开启了 设置->隐私->广告->限制广告跟踪之后 获取到的idfa将会是一串00000 跟mac地址一个尿性,而且每次开启在关闭之后 相应的idfa也会重新生成,相当于还原了一次广告标识符。

广告标识符.png

获取idfa的方法:

#import <AdSupport/AdSupport.h>

NSString *idfa = [[[ASIdentifierManager sharedManager] 
advertisingIdentifier] UUIDString];

iOS10 之后最好加一个判断[[ASIdentifierManager sharedManager] isAdvertisingTrackingEnabled] 返回值是BOOL值 如果返回的YES说明没有 “开启限制广告跟踪”,可以获取到正确的idfa 如果返回的是NO,说明等待你的就是一串00000000000

6.非Ad,模拟获取设备的 idfa

6.1 限制广告跟踪背景

中文说明文档

Important

In iOS 10.0 and later, the value of advertisingIdentifier is all 
zeroes when the user has limited ad tracking.

也就是说在iOS10上,用户如果开启了 限制广告跟踪 , 获取的idfa将是一串00000000-0000-0000-0000-000000000000

6.2 SimulateIDFA

SimulateIDFA是根据一堆设备信息(每个app获取的值都是一样的)生成的一个MD5值。用于标志不同设备。

6.2.1 使用

先去github下载代码

https://github.com/youmi/SimulateIDFA 

调用的方法

NSString *simulateIDFA = [SimulateIDFA createSimulateIDFA];

simulateIDFA的格式跟IDFA的格式一样

626363D0-90D4-06BF-C281-384E4E69D3E2
6.2.2 生成原理

生成的类似MD5值一样, 保持唯一性, 分两部分。

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

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

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

系统版本(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文件创建更新时间、系统容量

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

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

6.2.3 SimulateIDFA与OpenIDFA对比

OpenIDFA 是 Yann Lechelle的一个开源库。同是IDFA的替换方案

假设一个情况。一天内某个国家有10000000(1千万)台相同型号的设备升级到同一个系统。
1: SimulateIDFA一天内这个算法可能的值计算, 24x3600
(文件创建时间,单位秒)x 10
(文件最后修改时间假设误差在10秒)x 10000000
(系统容量误差范围)x 1000000
(设备名称范围,这里假设的是每100台就有2个重复)= 8640000000000000000
。设备a的值为 K,那么设备b的值同为K的可能性为: 1/8640000000000000000
. 总共有 10000000
台设备。因此,这10000000设备中有与a设备的值同为K的可能性为 1/8640000000000000000 x 10000000 = 1/864000000000。

A. 生成的ID重复的概率对比

假设一个情况。一天内某个国家有10000000(1千万)台相同型号的设备升级到同一个系统。

1.系统开机时间(1473241127 减去后四位值为 147324)、系统容量(29230571520)、
2.系统版本(9.3.4)、机型(N78AP,iPod5,1)、国家代码(CN)、本地语言(zh-Hans-CN)、
3.一些预装的App(由于用的是canOpenURL这个接口,iOS9就已经废了)、时区(Asia/Shanghai)、
4.当天时间(160804, 16年8月4日,这个值是他每天值都会变化的原因)

一天内可能的值为系统容量的误差(10000000)。 ps: 系统启动时间在这种情况下对重复率的降低没起到作用,因为OpenIDFA是减去了系统启动时间的后4位来计算的。同理当天时间也是。

设备a的值为 K,那么设备b的值同为K的可能性为: 1/10000000. 总共有 10000000台设备。因此,这10000000设备中有与a设备的值同为K的可能性为 1/10000000 x 10000000 = 1

B.时效性对比
6.2.4 总结:

OpenIDFA 有一些限制,生成的IDFA会每天变化,在一些极端条件下重复率比较高。 SimulateIDFA在这方面有更好的表现

7.iOS 提交审核之IDFA的介绍

7.1 提交审核

在我们提交程序进行审核的时候,最后会有两个选项供我们选择,一个是Export Compliance(该选项主要是说你的程序设计是否使用了加密,我一般上传的时候都选择No,这个根据你项目实际情况来选择.);另一个就是Advertising Identifier(广告标示符).

image.png image.png
各个选项的含义

1、 在 App 内投放广告服务应用中的广告。如果你的应用中集成了广告的时候,你需要勾选这一项。

2、 将此 App 安装归因于先前投放的特定广告跟踪广告带来的安装。如果你使用了第三方的工具来跟踪广告带来的激活以及一些其他事件,但是应用里并没有展示广告你需要勾选这一项。

3、将此 App 中发生的操作归因于先前投放的特定广告跟踪广告带来的用户的后续行为。如果你使用了第三方的工具来跟踪广告带来的激活以及一些其他事件。

4、 iOS 中的“限制广告跟踪”设置这一项下的内容其实就是对你的应用使用 IDFA 的目的做下确认,只要你选择了采集 IDFA,那么这一项都是需要勾选的。

总结

1: 如果你的应用里只是集成了广告,不追踪广告带来的激活行为,那么选择1和4;

2: 如果你的应用没有广告,而又获取了IDFA。建议选择2和4;

7.2检查是否使用IDFA

检查我们项目中是否使用广告标示符,其实就是查看我们-

(1)打开终端cd到要检查的文件的目录;
(2)执行命令:grep -r advertisingIdentifier .(注意别少了点);

分别对我的项目中和ShareSDK里面进行了检查:

image.png

总结写在后面

对于获取设备的唯一标识, 是一件众说纷纭的事情
因为从用户来角度说, 为了隐私和安全, 肯定不希望有任何数据泄露
但是从开发者(前端和服务端)角度来说, 拿到这个标识, 用于追踪数据和操作日志, 又是多么的重要的, 能快速定位到问题.
因为本人任职游戏研发, 有游客这个功能, 信息量是很少的, 根据 idfa 就能定位到很多问题, 总之
如果你的应用是广告类应用, 放心大胆的去获取苹果的 idfa 就可以
如果你的应用是非广告类的应该, 建议去用模拟 idfa 这个算法, 知名度和认可度较高,总之看需求

上一篇下一篇

猜你喜欢

热点阅读