Android唯一识别号(设备指纹)的生成及原理

来源:互联网 发布:淘宝上哪家燕窝是正品 编辑:程序博客网 时间:2024/06/04 01:36

目的:

尽可能实现,同一设备在不刷机不恢复出厂的情况下,每次生成的设备指纹不变;并且尽可能保证两部不同的设备生成的设备指纹不能一样)

原理:

1.将imei号+手机硬件信息+androidID拼接成一个字符串(由于个别手机某些时候获取的wifi MAC和蓝牙MAC不一致,故舍去这两项);
2.再用MD5把以上信息处理成32位的字符串;

参考:移动应用统计唯一ID的基本原理及 友盟UMID 方案解析

代码实现如下:

/**  * 获取设备指纹的工具类  *  * @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;      }  
0 0
原创粉丝点击