一:1.1 :UDIDcss
簡介:UDID的全稱是Unique Device Identifier
,顧名思義,它就是蘋果IOS設備的惟一識別碼,它由40個字符的字母和數字組成。在不少須要限制一臺設備一個帳號的應用中常常會用到。在iOS5中能夠獲取到設備的UDID,iOS7中已經徹底的禁用了它。iOS7以前的使用了的app若是在iOS7上運行,它不會返回設備的UDID,而是會返回一串字符串,以FFFFFFFF
開頭,跟着identifierForVendor
的十六進制值。html
獲取:[[UIDevice currentDevice] uniqueIdentifier]
python
廢棄:iOS6ios
簡介:iOS 6.0系統新增用於替換uniqueIdentifier
的接口。是給Vendor標識用戶用的,每一個設備在所屬同一個Vender的應用裏,都有相同的值。其中的Vender是指應用提供商,但準確點說,是經過BundleID
的DNS反轉的前兩部分進行匹配,若是相同就是同一個Vender,例如對於com.somecompany.appone
,com.somecompany.apptwo
這兩個BundleID來講,就屬於同一個Vender,共享同一個idfv的值。和idfa不一樣的是,idfv的值是必定能取到的,因此很是適合於做爲內部用戶行爲分析的主id,來標識用戶,替代OpenUDID。若是用戶將屬於此Vender的全部App卸載,則idfv的值會被重置,即再重裝此Vender的App,idfv的值和以前不一樣。git
identifierForVendor對供應商來講是惟一的一個值,也就是說,由同一個公司發行的的app在相同的設備上運行的時候都會有這個相同的標識符。然而,若是用戶刪除了這個供應商的app而後再從新安裝的話,這個標識符就會不一致。github
獲取:[[[UIDevice currentDevice] identifierForVendor] UUIDString]
算法
適用:iOS6.0+數組
例子:95955F33-BFBD-48BA-A630-86XXXXXX482D
bash
簡介:廣告標示符,適用於對外:例如廣告推廣,換量等跨應用的用戶追蹤等。但若是用戶徹底重置系統((設置程序 -> 通用 -> 還原 -> 還原位置與隱私
) ,這個廣告標示符會從新生成。另外若是用戶明確的還原廣告(設置程序-> 通用 -> 關於本機 -> 廣告 -> 還原廣告標示符) ,那麼廣告標示符也會從新生成。注意:若是程序在後臺運行,此時用戶「還原廣告標示符」,而後再回到程序中,此時獲取廣 告標示符並不會當即得到還原後的標示符。必需要終止程序,而後再從新啓動程序,才能得到還原後的廣告標示符。在同一個設備上的全部App都會取到相同的值,是蘋果專門給各廣告提供商用來追蹤用戶而設的,網絡
advertisingIdentifier會返回給在這個設備上全部軟件供應商相同的 一個值,因此只能在廣告的時候使用。這個值會由於不少狀況而有所變化,好比說用戶初始化設備的時候便會改,用戶關閉 而後打開 也會變
用戶能夠在 設置 -> 隱私 -> 廣告追蹤 裏重置此id的值,或限制此id的使用。
獲取:[[[ASIdentifierManager sharedManager] advertisingIdentifier] UUIDString]
;
適用:iOS6.0+
例子:9C287922-EE26-4501-94B5-DDEXXXXXX475
簡介:MAC地址在網絡上用來區分設備的惟一性,接入網絡的設備都有一個MAC地址,他們確定都是不一樣的,是惟一的。一部iPhone上可能有多個MAC地址,包括WIFI的、SIM的等,可是iTouch和iPad上就有一個WIFI的,所以只需獲取WIFI的MAC地址就行了,也就是en0的地址。MAC地址就如同咱們身份證上的身份證號碼,具備全球惟一性。但在iOS7以後,若是請求Mac地址都會返回一個固定值。
注意:因爲idfa會出現取不到的狀況,故毫不能夠做爲業務分析的主id,來識別用戶。 好比開啓限制廣告追蹤
廢棄:iOS7.0+
獲取:
- (NSString *)macAddress
{
int mib[6]; size_t len; char *buf; unsigned char *ptr; struct if_msghdr *ifm; struct sockaddr_dl *sdl; mib[0] = CTL_NET; mib[1] = AF_ROUTE; mib[2] = 0; mib[3] = AF_LINK; mib[4] = NET_RT_IFLIST; if ((mib[5] = if_nametoindex("en0")) == 0) { printf("Error: if_nametoindex error/n"); return NULL; } if (sysctl(mib, 6, NULL, &len, NULL, 0) < 0) { printf("Error: sysctl, take 1/n"); return NULL; } if ((buf = malloc(len)) == NULL) { printf("Could not allocate memory. error!/n"); return NULL; } if (sysctl(mib, 6, buf, &len, NULL, 0) < 0) { printf("Error: sysctl, take 2"); return NULL; } ifm = (struct if_msghdr *)buf; sdl = (struct sockaddr_dl *)(ifm + 1); ptr = (unsigned char *)LLADDR(sdl); NSString *outstring = [NSString stringWithFormat:@"%02x:%02x:%02x:%02x:%02x:%02x", *ptr, *(ptr+1), *(ptr+2), *(ptr+3), *(ptr+4), *(ptr+5)]; NSLog(@"outString:%@", outstring); free(buf); return [outstring uppercaseString]; }
簡介: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; }
簡介:雖然蘋果在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同樣在項目中使用)
ios10更新以後一旦開啓了 設置->隱私->廣告->限制廣告跟蹤
以後 獲取到的idfa將會是一串00000 跟mac地址一個尿性,並且每次開啓在關閉以後 相應的idfa也會從新生成,至關於還原了一次廣告標識符。
獲取idfa的方法:
#import <AdSupport/AdSupport.h> NSString *idfa = [[[ASIdentifierManager sharedManager] advertisingIdentifier] UUIDString];
ios10 以後最好加一個判斷[[ASIdentifierManager sharedManager] isAdvertisingTrackingEnabled]
返回值是BOOL值 若是返回的YES說明沒有 「開啓限制廣告跟蹤」,能夠獲取到正確的idfa 若是返回的是NO,說明等待你的就是一串00000000000
爲了保護用戶隱私,早在2012年就再也不容許其生態中的玩家獲取用戶的惟一標識符,可是商家在移動端打廣告的時候又但願能監控到每一次廣告投放的效果,所以,蘋果想出了折中的辦法,就是提供另一套和硬件無關的標識符,用於給商家監測廣告效果,同時用戶能夠在設置裏改變這串字符,致使商家沒有辦法長期跟蹤用戶行爲。這個就叫作廣告標識符(IDFA),設置路徑是「設置->隱私->廣告->還原廣告標識符」,以下圖所示(iOS9)
由於這個IDFA不是惟一的,因此一開始行業內是很抵觸的,千方百計去獲取UDID(跟手機綁定的,用戶不能改變),引發蘋果大怒,在13年時禁止全部App獲取UDID,不然不能上架,也正由於其生態的封閉性,才能迫使你們就範。雖然IDFA不是惟一的,可是畢竟賽過沒有,何況也沒有多少用戶會去更改。所以,通過幾番爭鬥,IDFA已經成爲通用的iPhone用戶標識符,這個過程分爲6個階段,我用下圖總結
然而在今年iOS10推出後,廣告界大爲震驚,由於蘋果推出了「限制廣告追蹤」功能,設置的路徑和iOS9一致。可能細心的人注意到了,這個功能並不是iOS10獨有啊,在以前的版本中也同樣存在。不過通過實際的測試,在iOS10以前,即便用戶打開這個功能,商家同樣能夠獲取IDFA,只不過與以前的不同了,每次切換這個開關與點擊「還原廣告標識符」的效果同樣。而iOS10就不同了,當用戶打開這個功能後,商家只能獲取到一連串無心義的0,這纔是廣告界大爲震驚的緣由所在
中文說明文檔
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
SimulateIDFA是根據一堆設備信息(每一個app獲取的值都是同樣的)生成的一個MD5值。用於標誌不一樣設備。
#######4.2.1 使用:
CoreTelephony.framework
https://github.com/youmi/SimulateIDFA (下載代碼)
在須要獲取 SimulateIDFA
的地方調用代碼:
NSString *simulateIDFA = [SimulateIDFA createSimulateIDFA];
simulateIDFA的格式跟IDFA的格式同樣
626363D0-90D4-06BF-C281-384E4E69D3E2
#######4.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秒的話會變,其餘參數在設置裏面能夠修改
OpenIDFA 是 Yann Lechelle的一個開源庫。同是IDFA的替換方案
#######4.3.1 生成的ID重複的機率對比
假設一個狀況。一天內某個國家有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。
2: OpenIDFA
先看一下OpenIDFA的生成算法,OpenIDFA是對下面的參數組合進行MD5.
系統開機時間(1473241127 減去後四位值爲 147324)、系統容量(29230571520)、 系統版本(9.3.4)、機型(N78AP,iPod5,1)、國家代碼(CN)、本地語言(zh-Hans-CN)、 一些預裝的App(因爲用的是canOpenURL這個接口,iOS9就已經廢了)、時區(Asia/Shanghai)、 當天時間(160804, 16年8月4日,這個值是他天天值都會變化的緣由)
一天內可能的值爲系統容量的偏差(10000000)。 ps: 系統啓動時間在這種狀況下對重複率的下降沒起到做用,由於OpenIDFA是減去了系統啓動時間的後4位來計算的。同理當天時間也是。
設備a的值爲 K,那麼設備b的值同爲K的可能性爲: 1/10000000. 總共有 10000000臺設備。所以,這10000000設備中有與a設備的值同爲K的可能性爲 1/10000000 x 10000000 = 1
#######4.3.2 時效性對比
1: OpenIDFA
天天獲取的值都不同
2: SimulateIDFA
SimulateIDFA
分兩部分,前16位是在系統升級的時候纔會變化,後16位用戶的某些行爲可能會致使值變化(例如:重啓手機、修改設備名稱、修改手機本地語言)
#######4.3.3 總結:
OpenIDFA 有一些限制,生成的IDFA會天天變化,在一些極端條件下重複率比較高。 SimulateIDFA在這方面有更好的表現
在咱們提交程序進行審覈的時候,最後會有兩個選項供咱們選擇,一個是Export Compliance
(該選項主要是說你的程序設計是否使用了加密,我通常上傳的時候都選擇No,這個根據你項目實際狀況來選擇.);另外一個就是Advertising Identifier
(廣告標示符).
#######5.1 檢查是否使用IDFA
檢查咱們項目中是否使用廣告標示符,其實就是查看咱們-
1: framework中是否有個叫作AdSupport.framework
的框架;
2: 若是檢查framework沒有,多是咱們接入的第三方里面有,用如下方法檢查第三方中是否包含有IDFA版本;
(1)打開終端cd到要檢查的文件的目錄; (2)執行命令:grep -r advertisingIdentifier .(注意別少了點);
分別對個人項目中和ShareSDK裏面進行了檢查:
#######5.2 各個選項的含義
一、 在 App 內投放廣告服務應用中的廣告。
若是你的應用中集成了廣告的時候,你須要勾選這一項。
二、 將此 App 安裝歸因於先前投放的特定廣告
跟蹤廣告帶來的安裝。若是你使用了第三方的工具來跟蹤廣告帶來的激活以及一些其餘事件,可是應用裏並無展現廣告你須要勾選這一項。
三、將此 App 中發生的操做歸因於先前投放的特定廣告
跟蹤廣告帶來的用戶的後續行爲。若是你使用了第三方的工具來跟蹤廣告帶來的激活以及一些其餘事件。
四、 iOS 中的「限制廣告
跟蹤」設置這一項下的內容其實就是對你的應用使用 IDFA 的目的作下確認,只要你選擇了採集 IDFA,那麼這一項都是須要勾選的。
#######5.3 總結
1: 若是你的應用裏只是集成了廣告,不追蹤廣告帶來的激活行爲,那麼選擇1和4;
2: 若是你的應用沒有廣告,而又獲取了IDFA。建議選擇2和4;
參考資料:
http://www.jianshu.com/p/e222ff751a97
ios10 獲取idfa的坑
手機更新到Ios10後獲取的idfa全是0?
http://www.cnblogs.com/zxykit/p/5320259.html
iOS10 IDFA 獲取不到問題解決
http://www.ithao123.cn/content-8688001.html
http://blog.csdn.net/kaitiren/article/details/52562556
iOS 提交審覈之IDFA的介紹