穩定獲取Android裝置唯一碼(UUID)的解決方案
最近做的一個專案中需要用到Android裝置唯一碼(UUID)來標識一臺裝置,
Android中裝置唯一碼有很多,如:MAC地址、IMEI號(DeviceId)、IMSI號、ANDROID_ID、序列號(SerialNumber)等,
但並不是所有裝置上都能穩定獲取到這些值。
最後專案中採用的是MAC地址。
先總結一些搜尋得知的各種值的缺點,再說說最後採用MAC地址的解決方案吧。
1.MAC地址:
獲取MAC地址的方法有兩種:
(1). 通過Linux命令查詢
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 |
public
String getMacAddress() { String macAddress = null ;
String str = "" ;
try {
//linux下查詢網絡卡mac地址的命令
Process pp = Runtime.getRuntime().exec( "cat /sys/class/net/wlan0/address" );
InputStreamReader ir = new InputStreamReader(pp.getInputStream());
LineNumberReader input = new LineNumberReader(ir);
for (; null
!= str;) {
str = input.readLine();
if (str != null ) {
macAddress = str.trim(); // 去空格
break ;
}
}
} catch (IOException ex) {
ex.printStackTrace();
}
return macAddress;
}
|
缺點:
在當前沒開啟WiFi的情況下獲取得到的MAC地址值為空,即使在執行這段程式碼前是有開啟過WiFi,而執行這段程式碼時WiFi狀態是關閉的,也不能獲取到MAC地址。
(2). 通過Android官方的WifiManager類獲取
1 2 3 4 5 6 7 8 9 10 11 |
public
String getMacAddress() { String macAddress = null ;
WifiManager wifiManager =
(WifiManager)MyApplication.getContext().getSystemService(Context.WIFI_SERVICE);
WifiInfo info = ( null == wifiManager ? null :
wifiManager.getConnectionInfo());
macAddress = info.getMacAddress();
return macAddress;
}
|
需要加入許可權
1 |
< uses-permission android:name = "android.permission.ACCESS_WIFI_STATE" />
|
缺點:
這種方法雖然能在當前Wifi狀態為關閉的情況下獲取到MAC地址,但前提是在手機開機後要開啟過一次Wifi,如果在某次開機後沒開啟過Wifi就呼叫這段程式碼,獲取地址也是為空。
網上給出的解釋是:WiFi的Mac address是一個被動資訊。一般在開機後,不會主動上報到系統裡。要待WiFi硬體啟動後,才會把有關Mac address資料記載入系統去。
2.IMEI號(DeviceId)、IMSI號:
1 2 3 |
TelephonyManager mTelephonyMgr = (TelephonyManager) getSystemServic(Context.TELEPHONY_SERVICE);
String imsi = mTelephonyMgr.getSubscriberId(); //獲取IMSI號
String imei = mTelephonyMgr.getDeviceId(); //獲取IMEI號
|
需要加入許可權
1 |
< uses-permission android:name = "android.permission.READ_PHONE_STATE" />
|
缺點:
IMEI號(國際移動裝置身份碼)、IMSI號(國際移動裝置識別碼)這兩個是有電話功能的移動裝置才具有,也就是說某些沒有電話功能的平板是獲取不到IMEI和IMSI號的。且在某些裝置上getDeviceId()會返回垃圾資料。
3.ANDROID_ID:
ANDROID_ID 是裝置首次啟動時由系統隨機生成的一串64位的十六進位制數字。
1 |
String ANDROID_ID = Settings.System.getString(getContentResolver(), Settings.System.ANDROID_ID);
|
缺點:
①.裝置刷機wipe資料或恢復出廠設定時ANDROID_ID值會被重置。
②.現在網上已有修改裝置ANDROID_ID值的APP應用。
③.某些廠商定製的系統可能會導致不同的裝置產生相同的ANDROID_ID。
④.某些廠商定製的系統可能導致裝置返回ANDROID_ID值為空。
⑤.CDMA裝置,ANDROID_ID和DeviceId返回的值相同
4.序列號SerialNumber:
從Android 2.3開始,通過android.os.Build.SERIAL方法可獲取到一個序列號。沒有電話功能的裝置也都需要上給出此唯一的序列號。
1 |
String SerialNumber = android.os.Build.SERIAL;
|
缺點:
在某些裝置上此方法會返回垃圾資料。
解決方案:
一種比較折衷的辦法,在獲取MAC地址之前先判斷當前WiFi狀態,若開啟了Wifi,則直接獲取MAC地址,若沒開啟Wifi,則用程式碼開啟Wifi,然後馬上關閉,再獲取MAC地址。
目前此方法測試成功,無論在哪種狀態下都能正確取得裝置的MAC地址(包括開機後未啟動過Wifi的狀態下),且在未開啟Wifi的狀態下,用程式碼開啟Wifi並馬上關閉,過程極短,不會影響到使用者操作。
程式碼如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
public
String getMacAddress() {
String macAddress = null ;
WifiManager wifiManager =
(WifiManager)MyApplication.getContext().getSystemService(Context.WIFI_SERVICE);
WifiInfo info = ( null == wifiManager ? null :
wifiManager.getConnectionInfo());
if (!wifiManager.isWifiEnabled())
{
//必須先開啟,才能獲取到MAC地址
wifiManager.setWifiEnabled( true );
wifiManager.setWifiEnabled( false );
}
if ( null != info) {
macAddress = info.getMacAddress();
}
return macAddress;
}
|
需要加入如下許可權
1 2 3 |
< uses-permission android:name = "android.permission.ACCESS_WIFI_STATE" >
</ uses-permission >
< uses-permission android:name = "android.permission.CHANGE_WIFI_STATE" >
</ uses-permission >
< uses-permission android:name = "android.permission.WAKE_LOCK" >
</ uses-permission >
|