IOS體系ID知多少?【技術類】

摘要:移動IOS設備體系ID您知道多少?

本系列第一篇《移動設備ID煩惱知多少?》已將ID的各種煩惱問題說了那麼多,下面我體系化地從IOS、Android兩大體系來詳解一下兩大體系中的各種設備ID吧:

先說IOS吧:2013年IOS6是一個巨大的分水嶺:

一、IMEI

在iOS5之後該方法就被廢棄掉了,因此iOS5以後不能獲取手機IMEI,但是也是可以通過私有API獲取手機的IMEI號的,但是通過蘋果私有API獲取IMEI號,上架蘋果商店會被拒掉的。

電信運營商因為通訊網路協議中都是傳遞用戶手機的IMEI及SIM卡的IMSI,所以運營商是有這些用戶的IMEI及IMSI的;

二、UDID

UDID的全稱是UniqueDevice Identifier,顧名思義,它就是蘋果IOS設備的唯一識別碼,它由40個字元的字母和數字組成。在很多需要限制一台設備一個賬號的應用中經常會用到。在iOS5中可以獲取到設備的UDID,iOS7中已經完全的禁用了它。iOS7之前的使用了的app如果在iOS7上運行,它不會返回設備的UDID,而是會返回一串字元串,以FFFFFFFF開頭,跟著identifierForVendor的十六進位值。

廢棄版本:iOS6

獲取代碼:[[UIDevice currentDevice] uniqueIdentifier]

AppleAccount(非法私有方法):雖然蘋果在iOS6中禁用了獲取UDID的方式,但是只要你研究下就知道這個API只是私有化了,使用私有API還是可以獲取設備的UDID。但是這個方法也面臨著風險:比如API變更以及AppStore審核問題,但是在越獄設備上你還是可以盡情享用的。

類:AADeviceInfo(dump出頭文件)

@classNSObject<OS_dispatch_semaphore>, APSConnection, NSData;

@interfaceAADeviceInfo : 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一樣在項目中使用)

三、無線網卡MAC地址

1、在App中編程獲取使用:

IOS7以後不能通過獲得MAC地址來標示手機唯一,App應用在iOS6及以下時,可以正確取道Mac地址,在iOS7上,會返回固定值。這樣帶來的問題是無法區分具體的iOS設備,有些產品就非常難搞了,目前沒有找到可以區分不同iOS設備的方法。測試過mac地址,確實會返回固定值02:00:00:00:00:00。

MAC地址在網路上用來區分設備的唯一性,接入網路的設備都有一個MAC地址,他們肯定都是不同的,是唯一的。一部iPhone上可能有多個MAC地址,包括WIFI的、SIM的等,但是iTouch和iPad上就有一個WIFI的,因此只需獲取WIFI的MAC地址就好了,也就是en0的地址。MAC地址就如同我們身份證上的身份證號碼,具有全球唯一性。但在iOS7之後,如果請求Mac地址都會返回一個固定值。

廢棄版本:iOS7.0+(當然App有一些特殊的方法,例如主動提示用戶選擇WIFI網路的方式可以獲取MAC地址。)

獲取代碼:

- (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_nametoindexerror/n");

return NULL;

}

if (sysctl(mib, 6, NULL, &len, NULL, 0)< 0) {

printf("Error: sysctl, take1/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, take2");

return NULL;

}

ifm = (struct if_msghdr *)buf;

sdl = (struct sockaddr_dl *)(ifm + 1);

ptr = (unsigned char *)LLADDR(sdl);

NSString *outstring = [NSStringstringWithFormat:@"%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];

}

2、WIFI上網成功後時WIFI AP可以獲取這個設備的MAC地址;

3、WIFI AP探針SSID廣播掃描已獲取不到IOS8以上手機的MAC地址;

IOS8在同WIFI AP探針SSID廣播掃描包通訊的時候,因為是非主動申請上網,所以IOS8都會隨機生成一個MAC地址來回應WIFI AP探針。導致WIFI AP探針獲取到假的MAC地址,以保護用戶隱私。

當然有一些特別的做法:例如將AP偽裝為用戶常用的」SSID」,例如:「CMCC」等等,IOS會主動嘗試連接,這個時候WIFI AP探針就獲取到了用戶真實的MAC地址。

四、IDFV

IDFV是App隔離的,某一App內部獲取到給用戶的IDFV是穩定不變的,但是不同App之間獲取的IDFV是不同的,意味著App內部要追蹤和分析用戶及個性化可以直接使用IDFV。而要跨App來追蹤這個用戶的設備IDFV就無能為力了。

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的值和之前不同。

適用:iOS6.0+

例子:95955F33-BFBD-48BA-A630-866D2DAE482D

獲取代碼:[[[UIDevice currentDevice]identifierForVendor] UUIDString]

五、IDFA

廣告標示符,適用於對外:例如廣告推廣,換量等跨應用的用戶追蹤等。

適用:iOS6.0+

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

獲取代碼:[[[ASIdentifierManager sharedManager] advertisingIdentifier]UUIDString];

詳細代碼如下:

a.添加框架

AdSupport.framework

b.添加頭文件

#import<AdSupport/ASIdentifierManager.h>

c.使用語句

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

NSLog(@"identifierForAdvertising ==%@",identifierForAdvertising)

廣告標示符是由系統存儲著的。不過即使這是由系統存儲的,但是有幾種情況下,會重新生成廣告標示符。如果用戶完全重置系統((設置程序 ->通用 -> 還原 ->還原位置與隱私),這個廣告標示符會重新生成。

另外如果用戶明確的還原廣告(設置程序->通用 -> 關於本機 ->廣告 ->還原廣告標示符),那麼廣告標示符也會重新生成。

關於廣告標示符的還原,有一點需要注意:如果程序在後台運行,此時用戶「還原廣告標示符」,然後再回到程序中,此時獲取廣告標示符並不會立即獲得還原後的標示符。必須要終止程序,然後再重新啟動程序,才能獲得還原後的廣告標示符。之所以會這樣,因為ASIdentifierManager是一個單例。

作為媒體方的App開啟IDFA注意:在App提交AppStore審核時,對於IDFA的用途請按下圖勾選,且在AppStore的審核人員審核操作時能看到Ad,否則App審核將被拒(無Ad不可使用IDFA)。

作為廣告主方App開啟IDFA注意:在App提交AppStore審核時,對於IDFA的用途請按下圖勾選,說明使用IDFA是為了作為廣告主要跟蹤廣告效果的需要(若被拒,可按此理由作為廣告主身份進行申訴。):

作為既具備媒體方及廣告主方特性的App開啟IDFA注意:在App提交AppStore審核時,對於IDFA的用途請按下圖勾選,且在AppStore的審核人員審核操作時能看到Ad,否則App審核將被拒(無Ad不可使用IDFA)

若按上述操作後App審核仍被拒,可開啟一個臨時的Ad(無Ad不可使用IDFA),審核通過後關閉該Ad(在AppStore的審核人員審核操作時能看到Ad即可),且可發送一個帶有Ad的截圖進行申訴。

附被拒提示:

提交App審核時若未勾上「使用了IDFA」被拒的提示如下: Improper Advertising Identifier [IDFA] Usage. Your app contains theAdvertising Identifier [IDFA] API but you have not indicated its usage on thePrepare for Upload page in iTunes Connect.

提交App審核是若未勾上「Limit Ad Tracking setting in iOS」被拒的提示如下: Improper Advertising Identifier [IDFA] Usage. Your app contains theAdvertising Identifier [IDFA] API but your app is not respecting the Limit AdTracking setting in iOS.

最近大家恐慌的IOS10 關閉廣告追蹤後 IDFA為一串「0000……」不必驚慌,因為早在IOS6的時候就已經有這個功能了也沒看到多大影響。一般IDFA是專門給「廣告用的」,而Iphone手機只要在出廠的時候沒有關閉「廣告追蹤」,很少有用戶會主動去設置關閉。(據不完全統計也就10%左右的專業用戶能找到那個藏的很深入的設置界面)。

同時IDFA由於是App獲取後需要通過業務程序發送給伺服器端的,所以電信運營商只有通過尋找業務數據包特徵碼的方式拆解業務數據包才能獲取IDFA。所以不能100%擁有IDFA。

六、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:(__bridgeid)kSecValueData];

if (UUID == nil || UUID.length == 0) {

UUID = [[[UIDevice currentDevice]identifierForVendor] UUIDString];

[keyChainWrapper setObject:UUIDforKey:(__bridge id)kSecValueData];

}

return UUID;

}

七、OpenUDID:(IOS7+已無法使用)

非Apple官方提供的Api,原理是由第一個使用openudid的app生成,並存放到系統粘貼版(具體也不理解什麼原理),之後安裝的其他app去粘貼版取。但ios7發布後,OpenUDID不能用了. OpenUDID是用系統粘貼板作為中間存儲供所有app調用. 新的系統把粘貼板的訪問許可權限制在了同一個開發者的範圍內,既同一個開發者的多個app在同個設備上共享粘貼板。

目前市場上IOS主要以IDFA作為廣告流量標識為主。

大家是不是已經徹底暈菜了?那我們休息一下,下篇再來看看「Android體系的各種ID」吧。

(轉載請註明出處:微信訂閱號:ad_automation)

文字的表現力畢竟有限,若大家還比較迷糊的話,歡迎參加「1.7號的線下大課堂」專門增加了針對移動ID的專題,可面對面為您答疑解惑講透這些問題。


推薦閱讀:

預算平滑(Budget Smooth)是怎樣花錢的?
肉刷——App推廣作弊內幕系列
為何國內的移動 SP 市場如此混亂?移動 SP 的發展前景可能在哪裡?
互聯網廣告領域的產品新人,如何構建知識體系?前輩們最推薦的10本書?

TAG:移动互联网广告 | 大数据 | iOS |