開篇
我又來寫簡書了,今天說一下設備的唯一識別碼,和怎么使用它吧。IOS系統中,獲取設備唯一標識的方法有很多,我們來介紹一下。
各種設備識別碼的介紹
- UDID(Unique Device Identifier)
UDID的全稱是Unique Device Identifier,顧名思義,它就是蘋果IOS設備的唯一識別碼,它由40個字符的字母和數字組成。 - UUID(Universally Unique Identifier)
UUID是Universally Unique Identifier的縮寫,中文意思是通用唯一識別碼. - MAC Address
MAC(Media Access Control或者Medium Access Control)地址,意譯為媒體訪問控制,或稱為物理地址、硬件地址,用來定義網絡設備的位置。在OSI模型中,第三層網絡層負責 IP地址,第二層數據鏈路層則負責 MAC地址。因此一個主機會有一個MAC地址,而每個網絡位置會有一個專屬于它的IP地址。MAC地址是網卡決定的,是固定的。 - OPEN UDID
設備的識別碼,每臺iOS設備的OpenUDID是通過第一個帶有OpenUDID SDK包的App生成,如果你完全刪除全部帶有OpenUDID SDK包的App(比如恢復系統等),那么OpenUDID會重新生成,而且和之前的值會不同,相當于新設備;
優點是沒有用到MAC地址;不同設備能夠獲取各自唯一的識別碼,保證了唯一性,可以用于以往UDID的相關用途;從代碼分析OpenUDID的獲取,識別碼獲取方便并且保存謹慎。缺點是當將設備上所有使用了OpenUDID方案的應用程序刪除,且設備關機重啟,xcode徹底清除并重啟,重裝應用程序去獲取OpenUDID,此時OpenUDID變化,與之前不一樣了,所有OpenUDID應用卸載后,由UIPasteboard保存的數據即被清除,重裝故會重新獲取新的OpenUDID。
那么當因為用戶干預或者惡意程序,致使UIPasteboard數據清除,從而導致OpenUDID被刪除,重裝也會獲取新的OpenUDID。 - 廣告標示符(IDFA-identifierForIdentifier)
廣告標示符,適用于對外:例如廣告推廣,換量等跨應用的用戶追蹤等。 - Vindor標示符 (IDFV-identifierForVendor)
Vendor是CFBundleIdentifier(反轉DNS格式)的前兩部分。來自同一個運營商的應用運行在同一個設備上,此屬性的值是相同的;不同的運營商應用運行在同一個設備上值不同。
經測試,只要設備上有一個tencent的app,重新安裝后的identifierForVendor值不變,如果tencent的app全部刪除,重新安裝后的identifierForVendor值改變。
分析
雖然我們看似有了那么多的唯一標識,但是不要高興的太早,上面所有這些表示設備唯一號的標識,在IOS7中要么被禁止使用,要么重新安裝程序后兩次獲取的標識符不一樣。
下面就項目中的事來說一下,我的成(辛)長(酸)歷(歷)程(史)。之前的一個項目中要與無線WIFI設備對接,來控制用戶使用無線網絡的情況,但是,硬件那邊來的技術小哥一口咬定要實現這個必須要設備的Mac地址,因為他們的無線設備就是根據mac地址來實現控制的,然后對我進行了瘋狂的灌輸,Mac地址的用處...此處省略無數字,但是我想說的是,高傲的蘋果不允許啊,蘋果已經不允許獲取用戶的Mac地址了,在iOS請求的Mac地址都會返回一個固定的值,你不是要用來用戶識別么,你識別啊,在iOS7后返回一臉的02:00:00:00:00:00。一切的轉機直到我聯系到了他們的技術總監,一個大一號的程序猿(~_ ~),然后事情就解決了,其實通過別的唯一標識符也是可以的。
UDID,Mac地址,OpenUDID,都已經要么無效要么禁止,那么我們就采用目前用的比較多的UUID吧。
UUID使用
首先我么要獲取設備的UUID啊,這個還是比較簡單的,上代碼
NSString *deviceUUID = [[[UIDevice currentDevice] identifierForVendor] UUIDString];
NSLog(@"%@",deviceUUID);
這樣我們就打印出了設備的UUID
2016-08-02 15:13:14.138 keychaintest[2002:222100] BDAF6B4D-5DC0-4AEF-BCF8-6C7EFC94DE97
但是問題來了,當我們從真機上卸載這個軟件重新安裝的時候,UUID變了(模擬器每次都變),對,確實變了
我們如果還要用UUID來作為唯一識別符的話,我們只能把他存在一個地方,讓軟件卸載的時候他也不會丟失,NSUserDefaults和FMDB等本地存儲已經不能再完成他們的使命了。怎么辦呢?
keychain的使用
keychain的使用確實幫我們解決了這個問題,我們可以在第一次生成我們需要的UUID的時候,保存他,然后就用keychain里保存的值來代替他的UUID,這樣卸載之后,生成新的UUID,但是keychain里的數據是不會消失的,這樣就實現了唯一識別碼的目的。
文檔上說iOS的keyChain是一個相對獨立的空間,當程序替換,刪除時并不會刪除keyChain的內容,這個要比Library/Cache好。刷機,恢復出廠應該就沒有了。關于備份,?只會備份數據,到那時不會備份設備的密鑰,換句話說,即使拿到數據,也沒有辦法解密里面的內容,感覺keyChain像是沙盒的升級版,可以存放一些非私密的信息,即使破解也不影響其它用戶,只影響那個破解了的設備。(比如針對該設備的一個密鑰)。
可訪問性一般來說,自己的程序只能訪問自己的keychain,相同bundle的程序通過設置group可以互相共享同組的keychain,從而實現程序間可以共同訪問一些數據。
說了那么多我們怎么使用它呢,蘋果給出了文檔,但是我們只是做簡單的數據的存儲,自己寫個簡單的類來實現它就好了。
然后實現它
這樣我們再調用它
[GSKeyChainDataManager saveUUID:deviceUUID]; //存入
[GSKeyChainDataManager readUUID] //讀取
進入設備的時候存入UUID,以后的時候讀取他。就算卸載,讀取出來的值還是第一次進入軟件的時候的UUID,實現了設備的唯一標識符。(注意寫的地方,不要每次運行都重新存儲,不要用模擬器)。
后記
keychain是非常有用的,可以幫我們保存用戶的賬號密碼等信息,我們可以通過自己寫的方法去存儲他。實現本地化保存,比以前的方法更加的安全哦。這里,如果有需要方法代碼的小伙伴,可以留下郵箱。
最新補充
最近由于工作以及各方面原因比較忙,所以很多留言也未發代碼,這里留一個git地址,有需要的自己去下載一下吧。SomeTools-Demo里面有幾個類似于工具類的代碼,比如正則表達式,定時器的封裝,GCD等知識,其中keychaintest是保存設備唯一標識符的代碼,有需要的可以去下一下,順便點個星哦,不用再留言了。
更正
此處的UUID 根本不是UUID ,是IDFV,設備的唯一標識用IDFV配合keychain來做的。