赞友商城电商平台排名第几,soe搜索优化,最好的网站模板,wordpress 当前文章标签前言项目开发中#xff0c;多少会遇到这种需求#xff1a;获得设备唯一标识DeviceId#xff0c;用于#xff1a;1.标识一个唯一的设备#xff0c;做数据精准下发或者数据统计分析#xff1b;2.账号与设备绑定#xff1b;3.....分析这类文章#xff0c;网上有许多资料多少会遇到这种需求获得设备唯一标识DeviceId用于1.标识一个唯一的设备做数据精准下发或者数据统计分析2.账号与设备绑定3.....分析这类文章网上有许多资料例如使用IMEI、MAC等作为设备标识使用。不过看过这些文章或者深入调研的同学应该都清楚这些数据均存在缺陷有的因为权限无法获取到有的获取出来是重复的有的完全获取不到也就是说不能完美的解决设备唯一的问题。那么用什么数据才能表示设备唯一呢方案方案1UUID SharePreference(存取)APP首次使用时创建UUID并保存到SharePreference中。
以后再次使用时直接从SharePreference取出来即可优点数据唯一、不需要权限
缺点会随APP一起删除即重新安装APPDeviceId值会改变新UUID方案2UUID SD卡存取APP首次使用时创建UUID并保存到SD卡中。
以后再次使用时直接从SD卡取出来即可
很多APP就是这么做的优点数据唯一、不随APP一起删除
缺点需要SD卡读写权限防不住用户手动删除SD卡的文件方案3imei android_id serial 硬件uuid自生成如果又想唯一又不想因用户的删除而重新生成UUID该怎么做呢 不依赖随机的UUID咱们根据硬件标识来创建唯一的数据我们可以将多个可获得的硬件标识拼接起来尽可能不依赖权限最大程度上降低重复性。
以imei、android_id、serial为例如果能取到值每个数据几乎可以代表唯一。
如果这些数据都能获取到拼起来的数据重复性降到极低UUID也存在重复性重复性极低而已那么哪些硬件标识合适呢AndroidId : 如df176fbb152ddce,无需权限,极个别设备获取不到数据或得到错误数据
serial如LKX7N18328000931,无需权限,极个别设备获取不到数据
IMEI : 如23b12e30ec8a2f17需要权限
Mac: 如6e:a5:....需要权限高版本手机获得数据均为 02:00.....不可使用
Build.BOARD 如BLA 主板名称,无需权限,同型号设备相同
Build.BRAND 如HUAWEI 厂商名称,无需权限,同型号设备相同
Build.HARDWARE 如kirin970 硬件名称,无需权限,同型号设备相同
Build......更多硬件信息略分析了这么多硬件标识我们就使用imei android_id serial 硬件UUID使用Build属性生成如果硬件信息不变则UUID值不变。这是我们项目的实际方案大家也可根据自己的需要自由组合硬件标识。那么问题又来了不同设备的硬件标识长度不同拼接处理的DeviceId字符串长度不同怎么才能统一长度呢 也很简单我们先拼接好DeviceId数据取其SHA1值再转16进制即可统一40位长度实现import android.content.Context;
import android.os.Build;
import android.provider.Settings;
import android.telephony.TelephonyManager;import java.security.MessageDigest;
import java.util.Locale;
import java.util.UUID;/*** author xc* date 2018/11/16* desc*/
public class DeviceIdUtil {/*** 获得设备硬件标识** param context 上下文* return 设备硬件标识*/public static String getDeviceId(Context context) {StringBuilder sbDeviceId new StringBuilder();//获得设备默认IMEI6.0 需要ReadPhoneState权限String imei getIMEI(context);//获得AndroidId无需权限String androidid getAndroidId(context);//获得设备序列号无需权限String serial getSERIAL();//获得硬件uuid根据硬件相关属性生成uuid无需权限String uuid getDeviceUUID().replace(-, );//追加imeiif (imei ! null imei.length() 0) {sbDeviceId.append(imei);sbDeviceId.append(|);}//追加androididif (androidid ! null androidid.length() 0) {sbDeviceId.append(androidid);sbDeviceId.append(|);}//追加serialif (serial ! null serial.length() 0) {sbDeviceId.append(serial);sbDeviceId.append(|);}//追加硬件uuidif (uuid ! null uuid.length() 0) {sbDeviceId.append(uuid);}//生成SHA1统一DeviceId长度if (sbDeviceId.length() 0) {try {byte[] hash getHashByString(sbDeviceId.toString());String sha1 bytesToHex(hash);if (sha1 ! null sha1.length() 0) {//返回最终的DeviceIdreturn sha1;}} catch (Exception ex) {ex.printStackTrace();}}//如果以上硬件标识数据均无法获得//则DeviceId默认使用系统随机数这样保证DeviceId不为空return UUID.randomUUID().toString().replace(-, );}//需要获得READ_PHONE_STATE权限6.0默认返回nullprivate static String getIMEI(Context context) {try {TelephonyManager tm (TelephonyManager)
context.getSystemService(Context.TELEPHONY_SERVICE);return tm.getDeviceId();} catch (Exception ex) {ex.printStackTrace();}return ;}/*** 获得设备的AndroidId** param context 上下文* return 设备的AndroidId*/private static String getAndroidId(Context context) {try {return Settings.Secure.getString(context.getContentResolver(),
Settings.Secure.ANDROID_ID);} catch (Exception ex) {ex.printStackTrace();}return ;}/*** 获得设备序列号如WTK7N16923005607, 个别设备无法获取** return 设备序列号*/private static String getSERIAL() {try {return Build.SERIAL;} catch (Exception ex) {ex.printStackTrace();}return ;}/*** 获得设备硬件uuid* 使用硬件信息计算出一个随机数** return 设备硬件uuid*/private static String getDeviceUUID() {try {String dev 3883756 Build.BOARD.length() % 10 Build.BRAND.length() % 10 Build.DEVICE.length() % 10 Build.HARDWARE.length() % 10 Build.ID.length() % 10 Build.MODEL.length() % 10 Build.PRODUCT.length() % 10 Build.SERIAL.length() % 10;return new UUID(dev.hashCode(),
Build.SERIAL.hashCode()).toString();} catch (Exception ex) {ex.printStackTrace();return ;}}/*** 取SHA1* param data 数据* return 对应的hash值*/private static byte[] getHashByString(String data){try{MessageDigest messageDigest MessageDigest.getInstance(SHA1);messageDigest.reset();messageDigest.update(data.getBytes(UTF-8));return messageDigest.digest();} catch (Exception e){return .getBytes();}}/*** 转16进制字符串* param data 数据* return 16进制字符串*/private static String bytesToHex(byte[] data){StringBuilder sb new StringBuilder();String stmp;for (int n 0; n data.length; n){stmp (Integer.toHexString(data[n] 0xFF));if (stmp.length() 1)sb.append(0);sb.append(stmp);}return sb.toString().toUpperCase(Locale.CHINA);}
}调用String deviceId DeviceIdUtil.getDeviceId(application);结果输出FE00DDE9298310CDFEEFE69229B8DB248534710F总结方案1局限性较大不建议使用方案2是很多软件采用的方案因很少有人删除SD卡文件但需要注意权限方案3相较于前两种方案限制性较小只要硬件信息不变结果就不变。而且该方案可自行定制组合。究竟哪种方案合适大家应根据自己的项目需求合理选择才是。