Android唯一識別號(裝置指紋)的生成及原理
阿新 • • 發佈:2019-01-08
目的:
儘可能實現,同一裝置在不刷機不恢復出廠的情況下,每次生成的裝置指紋不變;並且儘可能保證兩部不同的裝置生成的裝置指紋不能一樣)
原理:
1.將imei號+手機硬體資訊+androidID拼接成一個字串(由於個別手機某些時候獲取的wifi MAC和藍芽MAC不一致,故舍去這兩項);
2.再用MD5把以上資訊處理成32位的字串;
程式碼實現如下:
/**
* 獲取裝置指紋的工具類
*
* @author BarryHuang
* @DATE 2015-8-19
*/
public class FingerprintUtil {
private static final String TAG = FingerprintUtil.class.getSimpleName();
private static final String FINGER_PRINT = "fingerprint";
/**
* 獲取裝置指紋
* 如果從SharedPreferences檔案中拿不到,那麼重新生成一個,
* 並儲存到SharedPreferences檔案中。
*
* @param context
* @return fingerprint 裝置指紋
*/
public static String getFingerprint(Context context) {
String fingerprint = null;
fingerprint = readFingerprintFromFile(context);
if (TextUtils.isEmpty(fingerprint)) {
fingerprint = createFingerprint(context);
} else {
Log.e(TAG, "從檔案中獲取裝置指紋:" + fingerprint);
}
return fingerprint;
}
/**
* 從SharedPreferences 檔案獲取裝置指紋
*
* @return fingerprint 裝置指紋
*/
private static String readFingerprintFromFile(Context context) {
return PreferenceManager.getDefaultSharedPreferences(context).getString(FINGER_PRINT, null);
}
/**
* 生成一個裝置指紋(耗時50毫秒以內):
* 1.IMEI + 裝置硬體資訊(主要)+ ANDROID_ID + WIFI MAC組合成的字串
* 2.用MessageDigest將以上字串處理成32位的16進位制字串
*
* @param context
* @return 裝置指紋
*/
public static String createFingerprint(Context context) {
long startTime = System.currentTimeMillis();
// 1.IMEI
TelephonyManager TelephonyMgr = (TelephonyManager) context
.getSystemService(Context.TELEPHONY_SERVICE);
final String imei = TelephonyMgr.getDeviceId();
Log.i(TAG, "imei=" + imei);
//2.android 裝置資訊(主要是硬體資訊)
final String hardwareInfo = Build.ID + Build.DISPLAY + Build.PRODUCT
+ Build.DEVICE + Build.BOARD /*+ Build.CPU_ABI*/
+ Build.MANUFACTURER + Build.BRAND + Build.MODEL
+ Build.BOOTLOADER + Build.HARDWARE /* + Build.SERIAL */
+ Build.TYPE + Build.TAGS + Build.FINGERPRINT + Build.HOST
+ Build.USER;
//Build.SERIAL => 需要API 9以上
Log.i(TAG, "hardward info=" + hardwareInfo);
/* 3. Android_id 刷機和恢復出廠會變
* A 64-bit number (as a hex string) that is randomly
* generated when the user first sets up the device and should remain
* constant for the lifetime of the user's device. The value may
* change if a factory reset is performed on the device.
*/
final String androidId = Secure.getString(context.getContentResolver(),
Secure.ANDROID_ID);
Log.i(TAG, "android_id=" + androidId);
/**
* 4. The WLAN MAC Address string(個別手機剛開機完成後會獲取不到,捨去)
*/
/*WifiManager wifiMgr = (WifiManager) context
.getSystemService(Context.WIFI_SERVICE);
final String wifiMAC = wifiMgr.getConnectionInfo().getMacAddress();
Log.i(TAG,"wifi Mac="+wifiMAC);*/
/*
* 5. get the bluetooth MAC Address
* (有部分手機,如三星GT-S5660 2.3.3,當藍芽關閉時,獲取不到藍芽MAC;
* 所以為了保證 device id 的不變,捨去)
*/
/*BluetoothAdapter bluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
String bt_MAC = null;
if (bluetoothAdapter == null) {
Log.e(TAG, "bluetoothAdapter is null");
} else {
bt_MAC = bluetoothAdapter.getAddress();
}
Log.i(TAG,"m_szBTMAC="+bt_MAC);*/
// Combined Device ID
final String deviceId = imei + hardwareInfo + androidId/* + wifiMAC + bt_MAC*/;
Log.i(TAG, "deviceId=" + deviceId);
// 建立一個 messageDigest 例項
MessageDigest msgDigest = null;
try {
msgDigest = MessageDigest.getInstance("MD5");
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
}
//用 MessageDigest 將 deviceId 處理成32位的16進位制字串
msgDigest.update(deviceId.getBytes(), 0, deviceId.length());
// get md5 bytes
byte md5ArrayData[] = msgDigest.digest();
// create a hex string
String deviceUniqueId = new String();
for (int i = 0; i < md5ArrayData.length; i++) {
int b = (0xFF & md5ArrayData[i]);
// if it is a single digit, make sure it have 0 in front (proper
// padding)
if (b <= 0xF) deviceUniqueId += "0";
// add number to string
deviceUniqueId += Integer.toHexString(b);
// Log.i(TAG,"deviceUniqueId=" + deviceUniqueId);
} // hex string to uppercase
deviceUniqueId = deviceUniqueId.toUpperCase();
Log.d(TAG, "生成的裝置指紋:" + deviceUniqueId);
Log.e(TAG, "生成DeviceId 耗時:" + (System.currentTimeMillis() - startTime));
PreferenceManager.getDefaultSharedPreferences(context).edit().putString(FINGER_PRINT, deviceUniqueId).commit();
return deviceUniqueId;
}