iOS获取设备唯一标识的8种方法
8种iOS获取设备唯一标识的方法,希望对大家有用。
UDID
UDID(UniqueDeviceIdentifier),iOS设备的唯一识别码,是一个40位十六进制序列(越狱的设备通过某些工具可以改变设备的UDID),移动网络可以利用UDID来识别移动设备。
许多开发者把UDID跟用户的真实姓名、密码、住址、其它数据关联起来,网络窥探者会从多个应用收集这些数据,然后顺藤摸瓜得到这个人的许多隐私数据,同时大部分应用确实在频繁传输UDID和私人信息。为了避免集体诉讼,苹果最终决定在iOS5的时候,将这一惯例废除。
现在应用试图获取UDID已被禁止且不允许上架。
MAC地址
MAC(Medium/MediaAccessControl)地址,用来表示互联网上每一个站点的标示符,是一个六个字节(48位)的十六进制序列。前三个字节是由IEEE的注册管理机构RA负责给不同厂家分配的”编制上唯一的标示符(OrganizationallyUniqueIdentifier)”,后三个字节由各厂家自行指派给生产的适配器接口,称为扩展标示符。
MAC地址在网络上用来区分设备的唯一性,接入网络的设备都有一个MAC地址,他们肯定都是唯一的。一部iPhone上可能有多个MAC地址,包括WIFI的、SIM的等,但是iTouch和iPad上就有一个WIFI的,因此只需获取WIFI的MAC地址就好了。一般会采取MD5(MAC地址+bundleID)获取唯一标识。
但是MAC地址和UDID一样,存在隐私问题,iOS7之后,所有设备请求MAC地址会返回一个固定值,这个方法也不攻自破了。
OpenUDID
UDID被弃用后,广大开发者需要寻找一个可以替代的UDID,并且不受苹果控制的方案,由此,OpenUDID成为了当时使用最广泛的开源UDID代替方案。OpenUDID利用一个非常巧妙的方法在不同程序间存储标示符:在粘贴板中用了一个特殊的名称来存储标示符,通过这种方法,其他应用程序也可以获取。
苹果在iOS7之后对粘贴板做了限制,导致同一个设备上的应用间,无法再共享一个OpenUDID。
UUID+自己存储
UUID(UniversallyUniqueIDentifier),通用唯一标示符,是一个32位的十六进制序列,使用小横线来连接:8-4-4-4-12,通过NSUUID(iOS6之后)[NSUUIDUUID].UUIDString或者CFUUID(iOS2之后)CFBridgingRelease(CFUUIDCreateString(kCFAllocatorDefault,CFUUIDCreate(kCFAllocatorDefault)))来获取,但是每次获取的值都不一样,需要自己存储。
推送token+bundleID
推送token保证设备唯一,但是必须有网络情况下才能工作,该方法不依赖于设备本身,但依赖于applepush,而applepush有时候会抽风的。
IDFA
IDFA-identifierForIdentifier(广告标示符),在同一个设备上的所有APP都会取到相同的值,是苹果专门给各广告提供商用来追踪用户而设定的。虽然iPhone默认是允许追踪的,而且一般用户都不知道有这么个设置,但是用户可以在设置-隐私-广告追踪里重置此ID的值,或者限制此ID的使用,所以有可能会取不到值。
IDFV
IDFV-identifierForVendor(Vendor标示符),通过[UIDevicecurrentDevice].identifierForVendor.UUIDString来获取。是通过bundleID的反转的前两部分进行匹配,如果相同是同一个Vendor,例如对于com.mayan.app_1和com.mayan.app_2这两个bundleID来说,就属于同一个Vendor,共享同一个IDFV,和IDFA不同的是,IDFV的值一定能取到的,所以非常适合于作为内部用户行为分析的主ID来识别用户。但是用户删除了该APP,则IDFV值会被重置,再次安装此APP,IDFV的值和之前的不同。
IDFV+keychain
通过以上几种储存唯一标识的方法的分析,总结一下各有优劣。很多方法被苹果禁止或者漏洞太多,越来越不被开发者使用,现在苹果主推IDFA和IDFV这两种方法,分别对外和对内,但是IDFV在APP重新安装时会更改,所以我的方法是通过第一次生成的IDFV存储到keychain中,以后每次获取标识符都从keychain中获取。
#import<UIKit/UIKit.h> @interfaceMYVendorToll:NSObject +(NSString*)getIDFV; @end
#import"MYVendorToll.h" #import"MYKeyChainTool.h" @implementationMYVendorToll +(NSString*)getIDFV { NSString*IDFV=(NSString*)[MYKeyChainToolload:@"IDFV"]; if([IDFVisEqualToString:@""]||!IDFV){ IDFV=[UIDevicecurrentDevice].identifierForVendor.UUIDString; [MYKeyChainToolsave:@"IDFV"data:IDFV]; } returnIDFV; } @end
#import<Foundation/Foundation.h> @interfaceMYKeyChainTool:NSObject +(void)save:(NSString*)servicedata:(id)data; +(id)load:(NSString*)service; +(void)deleteKeyData:(NSString*)service; @end
#import"MYKeyChainTool.h" @implementationMYKeyChainTool +(NSMutableDictionary*)getKeychainQuery:(NSString*)service{ return[NSMutableDictionarydictionaryWithObjectsAndKeys: (id)kSecClassGenericPassword,(id)kSecClass, service,(id)kSecAttrService, service,(id)kSecAttrAccount, (id)kSecAttrAccessibleAfterFirstUnlock,(id)kSecAttrAccessible, nil]; } +(void)save:(NSString*)servicedata:(id)data{ //Getsearchdictionary NSMutableDictionary*keychainQuery=[selfgetKeychainQuery:service]; //Deleteolditembeforeaddnewitem SecItemDelete((CFDictionaryRef)keychainQuery); //Addnewobjecttosearchdictionary(Attention:thedataformat) [keychainQuerysetObject:[NSKeyedArchiverarchivedDataWithRootObject:data]forKey:(id)kSecValueData]; //Additemtokeychainwiththesearchdictionary SecItemAdd((CFDictionaryRef)keychainQuery,NULL); } +(id)load:(NSString*)service{ idret=nil; NSMutableDictionary*keychainQuery=[selfgetKeychainQuery:service]; //Configurethesearchsetting //Sinceinoursimplecaseweareexpectingonlyasingleattributetobereturned(thepassword)wecansettheattributekSecReturnDatatokCFBooleanTrue [keychainQuerysetObject:(id)kCFBooleanTrueforKey:(id)kSecReturnData]; [keychainQuerysetObject:(id)kSecMatchLimitOneforKey:(id)kSecMatchLimit]; CFDataRefkeyData=NULL; if(SecItemCopyMatching((CFDictionaryRef)keychainQuery,(CFTypeRef*)&keyData)==noErr){ @try{ ret=[NSKeyedUnarchiverunarchiveObjectWithData:(__bridgeNSData*)keyData]; }@catch(NSException*e){ NSLog(@"Unarchiveof%@failed:%@",service,e); }@finally{ } } if(keyData) CFRelease(keyData); returnret; } +(void)deleteKeyData:(NSString*)service{ NSMutableDictionary*keychainQuery=[selfgetKeychainQuery:service]; SecItemDelete((CFDictionaryRef)keychainQuery); } @end
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持毛票票。