如何唯一的標識一臺Android裝置
首先說結論我們到底能不能唯一的標識一臺Android裝置?很遺憾,暫時沒有一個很完美的方法能夠解決這個問題。Android開發者部落格的原文是:
Suppose you feel that for the needs of your application, you need an actual hardware device identifier. This turns out to be a tricky problem.
既然這樣,我們就來談談那些不太完美的方法。在這之前我們需要先知道幾個概念:
UUID : (Universally Unique Identifier)全域性唯一識別符號,是指在一臺機器上生成的數字,它保證對在同一時空中的所有機器都是唯一的。由以下幾部分的組合:當前日期和時間(UUID的第一個部分與時間有關,如果你在生成一個UUID之後,過幾秒又生成一個UUID,則第一個部分不同,其餘相同),時鐘序列,全域性唯一的IEEE機器識別號(如果有網絡卡,從網絡卡獲得,沒有網絡卡以其他方式獲得)。
IMEI : (International Mobile Equipment Identity) 是國際移動裝置身份碼的縮寫,國際移動裝備辨識碼,是由15位數字組成的"電子串號",它與每臺手機一一對應,而且該碼是全世界唯一的。
MEID :( Mobile Equipment IDentifier )是全球唯一的56bit CDMA制式移動終端標識號。標識號會被燒入終端裡,並且不能被修改。可用來對CDMA制式移動式裝置進行身份識別和跟蹤。
兩者的區別在於:IMEI是手機的身份證,MEID是CDMA制式(電信運營的)的專用身份證;IMEI是15位,MEID是14位。
DEVICE_ID
根據不同的手機裝置返回IMEI,MEID或者ESN碼,可以根據以下程式碼獲得:
Device_Id
非手機裝置:最開始搭載Android系統都手機裝置,而現在也出現了非手機裝置:如平板電腦、電視、音樂播放器等。這些裝置沒有通話的硬體功能,系統中也就沒有TELEPHONY_SERVICE,自然也就無法通過上面的方法獲得DEVICE_ID。
許可權問題:獲取DEVICE_ID需要READ_PHONE_STATE許可權,在Android 6.0上使用執行時動態授予許可權的機制,一旦使用者不給予授權,將獲取不到DEVICE_ID。
廠商定製系統中的Bug:少數手機裝置上,由於該實現有漏洞,會返回垃圾(這是開發者部落格的原話,沒有實踐過)。
MAC ADDRESS
MAC_Address
可以使用手機WiFi或藍芽的MAC地址作為裝置標識,但是並不推薦這麼做,原因有以下兩點:
硬體限制:並不是所有的裝置都有WiFi和藍芽硬體,硬體不存在自然也就得不到這一資訊。
獲取的限制:如果WiFi沒有開啟過,是無法獲取其Mac地址的;而藍芽是隻有在開啟的時候才能獲取到其Mac地址。
Serial Number
硬體序列,在Android 2.2 以上可以通過 android.os.Build.SERIAL 獲得序列號。在一些沒有電話功能的裝置會提供,某些手機上也可能提供(所以就是經常會返回Unknown)
ANDROID_ID
ANDROID_ID是裝置第一次啟動時產生和儲存的64bit的一個數,當裝置被wipe後該數重置。
Android_Id
ANDROID_ID似乎是獲取Device ID的一個好選擇,但它也有缺陷:在主流廠商生產的裝置上,有一個很經常的bug,就是每個裝置都會產生相同的ANDROID_ID:9774d56d682e549c 。同時刷機,或者重置ANDROID_ID的值都會變化。
接下來就來看看實際的標識方法:
第一種:Installtion ID
在程式安裝後第一次執行時生成一個ID,該方式和裝置唯一標識不一樣,不同的應用程式會產生不同的ID,同一個程式重新安裝也會不同。所以這不是裝置的唯一ID,但是可以保證每個使用者的ID是不同的。 可以說是用來標識每一份應用程式的唯一ID(即Installtion ID),可以用來跟蹤應用的安裝數量等(其實就是UUID)。
Installtion Id 獲取方法
第二種:UniquePsuedoID
通過讀取裝置的ROM版本號、廠商名、CPU型號和其他硬體資訊來組合出一串15位的號碼和裝置硬體序列號作為種子生成UUID。一串15位的號碼(批量生產的裝置每項資訊基本相同,所以這一段相同的可能性特別高);硬體序列,在一些沒有電話功能的裝置會提供,某些手機上也可能提供(Devices without telephony are required to report a unique device ID here; some phones may do so also.),所以就是經常會返回Unknown。
UniquePsuedoID 獲取方法
第三種:Universal ID
首先通過讀取Android_id,作為UUID的種子。若得到Android_Id等於9774d56d682e549c或者 發生錯誤則random一個UUID作為備用方案,最後把得到的UUID同時存入內部儲存和外部儲存。下次使用UUID的時候優先從外部儲存讀取,再從背部儲存讀取,最後在重新生成,儘可能的保證其不變性。
Universal_id獲取方法