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
- Android唯一识别号(设备指纹)的生成及原理
- Android唯一识别号(设备指纹)的生成
- Android 唯一设备号生成方案
- android证书指纹的生成
- Android唯一识别号
- Android唯一识别号
- android系统获取系统相关信息(如Android设备的唯一ID等)原理
- Android 设备指纹
- 设备唯一识别IDFA的构建与保证二次安装唯一性(ios自学笔记)
- Android 设备唯一标识生成方式
- Android 设备唯一标识生成方式
- android设备唯一码的获取之一手机串号IMEI和网络识别号imsi等
- 获取Android设备的唯一识别码|设备号|序号|UUID
- 获取Android设备的唯一识别码|设备号|序号|UUID
- 获取Android设备的唯一识别码|设备号|序号|UUID
- 获取Android设备的唯一识别码|设备号|序号|UUI
- 获取Android设备的唯一识别码|设备号|序号|UUID
- 获取Android设备的唯一识别码|设备号|序号|UUID
- Carthage 使用
- 几种Servlet加载方式以及在servlet中调用bean对象
- 排序
- Hibername三种状态(瞬时态 持久态 游离态)
- 打包后的apk微信分享依然失败
- Android唯一识别号(设备指纹)的生成及原理
- 用HttpSessionListener与HttpSessionBindingListener实现在线人数统计
- 剑指offer-二叉搜索树的第K个节点
- 使用TensorFlow实现余弦距离/欧氏距离(Euclidean distance)以及Attention矩阵的计算
- servlet的单线程模式
- Redis学习例子
- c++:函数返回引用类型和非引用类型
- The C++ Programming Language 读书笔记(四)
- js 匿名函数学习