iOS獲取設備ID總結(jié)
UDID
簡介:UDID的全稱是Unique Device Identifier,顧名思義,它就是蘋果IOS設備的唯一識別碼,它由40個字符的字母和數(shù)字組成。在很多需要限制一臺設備一個賬號的應用中經(jīng)常會用到。在iOS5中可以獲取到設備的UDID,iOS7中已經(jīng)完全的禁用了它。iOS7之前的使用了的app如果在iOS7上運行,它不會返回設備的UDID,而是會返回一串字符串,以FFFFFFFF開頭,跟著identifierForVendor的十六進制值。
獲取:[[UIDevice currentDevice] uniqueIdentifier]
廢棄:iOS6
IDFV
簡介:iOS 6.0系統(tǒng)新增用于替換uniqueIdentifier的接口。是給Vendor標識用戶用的,每個設備在所屬同一個Vender的應用里,都有相同的值。其中的Vender是指應用提供商,但準確點說,是通過BundleID的DNS反轉(zhuǎn)的前兩部分進行匹配,如果相同就是同一個Vender,例如對于com.somecompany.appone,com.somecompany.apptwo這兩個BundleID來說,就屬于同一個Vender,共享同一個idfv的值。和idfa不同的是,idfv的值是一定能取到的,所以非常適合于作為內(nèi)部用戶行為分析的主id,來標識用戶,替代OpenUDID。如果用戶將屬于此Vender的所有App卸載,則idfv的值會被重置,即再重裝此Vender的App,idfv的值和之前不同。
獲取:[[[UIDevice currentDevice] identifierForVendor] UUIDString]
適用:iOS6.0+
例子:95955F33-BFBD-48BA-A630-866D2DAE482D
IDFA
簡介:廣告標示符,適用于對外:例如廣告推廣,換量等跨應用的用戶追蹤等。但如果用戶完全重置系統(tǒng)((設置程序 -> 通用 -> 還原 -> 還原位置與隱私) ,這個廣告標示符會重新生成。另外如果用戶明確的還原廣告(設置程序-> 通用 -> 關(guān)于本機 -> 廣告 -> 還原廣告標示符) ,那么廣告標示符也會重新生成。注意:如果程序在后臺運行,此時用戶“還原廣告標示符”,然后再回到程序中,此時獲取廣 告標示符并不會立即獲得還原后的標示符。必須要終止程序,然后再重新啟動程序,才能獲得還原后的廣告標示符。在同一個設備上的所有App都會取到相同的值,是蘋果專門給各廣告提供商用來追蹤用戶而設的,用戶可以在 設置 -> 隱私 -> 廣告追蹤 里重置此id的值,或限制此id的使用。
獲?。篬[[ASIdentifierManager sharedManager] advertisingIdentifier] UUIDString];
適用:iOS6.0+
例子:9C287922-EE26-4501-94B5-DDE6F83E1475
MAC地址
簡介:MAC地址在網(wǎng)絡上用來區(qū)分設備的唯一性,接入網(wǎng)絡的設備都有一個MAC地址,他們肯定都是不同的,是唯一的。一部iPhone上可能有多個MAC地址,包括WIFI的、SIM的等,但是iTouch和iPad上就有一個WIFI的,因此只需獲取WIFI的MAC地址就好了,也就是en0的地址。MAC地址就如同我們身份證上的身份證號碼,具有全球唯一性。但在iOS7之后,如果請求Mac地址都會返回一個固定值。
廢棄:iOS7.0+
獲?。?/p>
- (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];
}
KeyChain
簡介:iOS整個系統(tǒng)有一個KeyChain,每個程序都可以往KeyChain中記錄數(shù)據(jù),而且只能讀取到自己程序記錄在KeyChain中的數(shù)據(jù)。而且就算我們程序刪除掉,系統(tǒng)經(jīng)過升級以后再安裝回來,依舊可以獲取到與之前一致的UDID(系統(tǒng)還原、刷機除外)。因此我們可以將UUID的字符串存儲到KeyChain中,然后下次直接從KeyChain獲取UUID字符串。(本示例中使用KeychainItemWrapper工具類)
獲?。?/p>
+ (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;
}
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或者直接使用該類就行。(細節(jié)補充:導出AppleAccount.framework后,進入AppleAccount.framework的根目錄,新建Headers文件夾,然后將dump出的頭文件放在Headers目錄,就可以像引用第三方framework一樣在項目中使用)