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


  • 2
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值