由于安卓平臺的開放性和碎片化,對于我們獲取唯一可靠的設備標識符帶來了很大的困難,在本片文章中我們將介紹安卓平臺下的,各種獲取設備標識符的方式以及這些方式的利弊,那什么是設備標識符呢?
簡單說,設備標識符就是唯一標識該設備的一串代碼或符號。
設備標識符在Android開發中的作用
- 跟蹤用戶安裝
- 識別物理設備
獲取Android設備ID(DeviceId)
設備ID(DeviceId)是手機唯一標識符,屬于比較穩定的設備標識符。對于GSM返回IMEI,對于CDMA返回MEID或ESN。
//uses-permission android:name="android.permission.READ_PHONE_STATE"
private String getDeviceId() {
TelephonyManager telephonyManager = (TelephonyManager) getSystemService(Context.TELEPHONY_SERVICE);
String deviceId = telephonyManager.getDeviceId();
return deviceId;
}
缺陷:
- 非手機設備沒有這種唯一的標識符,比如平板電腦、機頂盒、音樂播放器等。
- 權限問題:調用方法需要READ_PHONE_STATE權限,特別是Android 6.0以后,權限需要用戶手動確認。
- Bug:在一些設備制造商的設備上,這個只是不準確的 ,比如會返回一堆0或者星號。
獲取Mac Address
通過檢索設備的Wi-Fi或者藍牙硬件是有可能取得設備的Mac地址的。
// uses-permission android:name="android.permission.ACCESS_WIFI_STATE"
private String getWifiMacDId() {
WifiManager wifiManager = (WifiManager) getSystemService(Context.WIFI_SERVICE);
String wifMacId = wifiManager.getConnectionInfo().getMacAddress();
return wifMacId;
}
//uses-permission android:name="android.permission.BLUETOOTH"
private String getBlueToothMacDId() {
BluetoothAdapter bluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
String blueToothMacId = bluetoothAdapter.getAddress();
return blueToothMacId;
}
缺陷:
- 硬件限制: 并不是所有的設備都有WiFi和藍牙硬件
- 權限問題:需要ACCESS_WIFI_STATE或者BLUETOOTH權限
- 系統限制:為了保護用戶隱私,從Android 6.0開始將不能獲取WIFI和藍牙有效地Mac地址(02:0:00:00:00:0)
SERIAL
從Android 2.3 開始,可以獲取設備的硬件序列號
private String getSerialId(){
return android.os.Build.SERIAL;
}
缺陷:
Bug:可能不存在序列號的情況
Sim Serial Number 獲取SIM卡的序列號
//uses-permission android:name="android.permission.READ_PHONE_STATE"
private String getSimSerialNumber() {
TelephonyManager telephonyManager = (TelephonyManager) getSystemService(Context.TELEPHONY_SERVICE);
String simSerialNumber = telephonyManager.getSimSerialNumber();
return simSerialNumber;
}
缺陷:
- 設備限制:僅裝有SIM卡的設備才能獲取到
- 權限問題:調用方法需要READ_PHONE_STATE權限,特別是Android 6.0以后,權限需要用戶手動確認。
- Bug :對于CDMA設備,返回的是一空值
Android ID
設備第一次啟動時產生和存儲的 64-bit 字符串
private String getAndroidId() {
return Settings.Secure.getString(getContentResolver(), Settings.Secure.ANDROID_ID);
}
缺陷:
- 恢復出廠設置后可能會重置該值。
- 部分設備由于制造商錯誤實現,導致返回相同的 Android_ID 。
- 在 Android 4.2 及以上,設備啟用多用戶功能后,每個用戶的 Android ID 不同。
UUID
全局唯一標識符,是指在一臺機器上生成的數字,它保證對在同一個時空中所有的機器都是唯一的
private String getUUID() {
return java.util.UUID.randomUUID().toString();
}
缺陷:
- 和設備無關,不同的應用會產生不同的ID,無法做到設備唯一
如何選擇設備標識符
- 跟蹤用戶安裝,不需要嚴格意義上設備唯一的ID,使用UUID即可跟蹤用戶的安裝
- 識別物理設備,使用多個硬件標識符進行拼裝
private String getUUID() {
return md5(androidId()+serialNumber()+" ");
}
識別模擬器
public static boolean runnigOnEmulator() {
if (!TextUtils.isEmpty(Build.MODEL) && Build.MODEL.toLowerCase().contains("sdk")) {
return true;
}
if (!TextUtils.isEmpty(Build.MANUFACTURER) && Build.MANUFACTURER.toLowerCase().contains("unknown")) {
return true;
}
if (!TextUtils.isEmpty(Build.DEVICE) && Build.DEVICE.toLowerCase().contains("generic")) {
return true;
}
return false;
}