1. 程式人生 > >Android唯一識別號(裝置指紋)的生成及原理

Android唯一識別號(裝置指紋)的生成及原理

目的:

儘可能實現,同一裝置在不刷機不恢復出廠的情況下,每次生成的裝置指紋不變;並且儘可能保證兩部不同的裝置生成的裝置指紋不能一樣)

原理:

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; }