Android開發中有時候因業務需要客戶端要產生一個唯一的標識符使服務器能識別某台Android設備,目前一般使用三種標識符分別為 DeviceId
、 AndroidId
、 MAC地址
。
獲取DeviceId
在獲取deviceId之前先要要 AndroidManifest
中聲明權限:
<uses-permission android:name="android.permission.READ_PHONE_STATE" />
通過以下代碼獲取DeviceId:
public static String getDeviceId(Context context){ String deviceId = null; if(ContextCompat.checkSelfPermission(context, Manifest.permission.READ_PHONE_STATE) == PackageManager.PERMISSION_GRANTED) { TelephonyManager tm = (TelephonyManager) context.getSystemService(Context.TELEPHONY_SERVICE); deviceId = tm.getDeviceId(); } return deviceId; }
在獲取設備ID時應該注意:
- 需要
READ_PHONE_STATE
權限 - 在6.0或更高的設備上時因為權限要在運行時請求而
READ_PHONE_STATE
是一個dangerous
權限用戶極有可能不允許這個權限請求
獲取AndroidId
獲取AndroidId是不需要權限的但是AndroidId是可能變的,AndroidId是在用戶第一次激活這個設備時產生的所以當用戶重置手機時AndroidId會產生變化,理論上這個AndroidId是可以接受的畢竟重置手機這個事發生也不會太頻繁。
獲取AndroidId:
public static String getAndroidId(Context context){ return Settings.Secure.getString(context.getContentResolver(), Settings.Secure.ANDROID_ID); }
獲取MAC地址
可以使用WIFI的MAC地址來作為標識符,感覺現階段這種方式比較可靠總結如下:
- Mac地址是唯一的
- 直接產生在硬件上基本上不會變更
- 不需要額外的權限
- 向上或向下兼容
public static String getMacAddress(Context context) { String macAddress = null; try{ String wifiInterfaceName = "wlan0"; Enumeration<NetworkInterface> interfaces = NetworkInterface.getNetworkInterfaces(); while (interfaces.hasMoreElements()) { NetworkInterface iF = interfaces.nextElement(); if(iF.getName().equalsIgnoreCase(wifiInterfaceName)) { byte[] addr = iF.getHardwareAddress(); if (addr == null || addr.length == 0) { return null; } StringBuilder buf = new StringBuilder(); for (byte b : addr) { buf.append(String.format("%02X:", b)); } if (buf.length() > 0) { buf.deleteCharAt(buf.length() - 1); } macAddress = buf.toString(); break; } } }catch (SocketException se){ macAddress = null; } if(TextUtils.isEmpty(macAddress)){ android.net.wifi.WifiManager wifi = (android.net.wifi.WifiManager) context.getSystemService(Context.WIFI_SERVICE); macAddress = wifi.getConnectionInfo().getMacAddress(); } return macAddress; }
使用Android自帶的API時有個坑WifiInfo里面有這樣一段代碼:
/** * Default MAC address reported to a client that does not have the * android.permission.LOCAL_MAC_ADDRESS permission. * * @hide */ public static final String DEFAULT_MAC_ADDRESS = "02:00:00:00:00:00";
上面的代碼是從6.0API復制出來的意思是說如果你沒有說明android.permission.LOCAL_MAC_ADDRESS
權限那么將返回這個默認的MAC地址我在6.0上的機器上試了一下好像並沒有像它說的那樣我聲明android.permission.LOCAL_MAC_ADDRESS
僅限后還是拿到這個默認的MAC地址。也沒有繼續深究發現通過JAVA的API也是可以使到MAC地址的。