android 唯一识别码笔记

1.mac 地址,在 Android 6.0(API 级别 23)及更高版本中,本地设备 MAC 地址(例如 WLAN 和蓝牙)无法通过第三方 API 获取WifiInfo.getMacAddress() 方法和 BluetoothAdapter.getDefaultAdapter().getAddress() 方法都会返回 02:00:00:00:00:00,但可以通过其他方法获取。下面是找到的一个有效的方法,在6.0,7.0设备上可以获取到。

public final class DeviceUtils {

    private DeviceUtils() {
        throw new UnsupportedOperationException("u can't instantiate me...");
    }



    /**
     * Return version code of device's system.
     *
     * @return version code of device's system
     */
    public static int getSDKVersionCode() {
        return Build.VERSION.SDK_INT;
    }

    /**
     * Return the android id of device.
     *
     * @return the android id of device
     */
    @SuppressLint("HardwareIds")
    public static String getAndroidID() {
        return Settings.Secure.getString(
                Utils.getApp().getContentResolver(),
                Settings.Secure.ANDROID_ID
        );
    }

    /**
     * Return the MAC address.
     * 

Must hold * {@code }, * {@code }

* * @return the MAC address */ @RequiresPermission(allOf = {ACCESS_WIFI_STATE, INTERNET}) public static String getMacAddress() { String macAddress = getMacAddressByWifiInfo(); if (!"02:00:00:00:00:00".equals(macAddress)) { return macAddress; } macAddress = getMacAddressByNetworkInterface(); if (!"02:00:00:00:00:00".equals(macAddress)) { return macAddress; } macAddress = getMacAddressByInetAddress(); if (!"02:00:00:00:00:00".equals(macAddress)) { return macAddress; } macAddress = getMacAddressByFile(); if (!"02:00:00:00:00:00".equals(macAddress)) { return macAddress; } return "please open wifi"; } @SuppressLint({"HardwareIds", "MissingPermission"}) private static String getMacAddressByWifiInfo() { try { Context context = Utils.getApp().getApplicationContext(); WifiManager wifi = (WifiManager) context.getSystemService(Context.WIFI_SERVICE); if (wifi != null) { WifiInfo info = wifi.getConnectionInfo(); if (info != null) return info.getMacAddress(); } } catch (Exception e) { e.printStackTrace(); } return "02:00:00:00:00:00"; } private static String getMacAddressByNetworkInterface() { try { Enumeration nis = NetworkInterface.getNetworkInterfaces(); while (nis.hasMoreElements()) { NetworkInterface ni = nis.nextElement(); if (ni == null || !ni.getName().equalsIgnoreCase("wlan0")) continue; byte[] macBytes = ni.getHardwareAddress(); if (macBytes != null && macBytes.length > 0) { StringBuilder sb = new StringBuilder(); for (byte b : macBytes) { sb.append(String.format("%02x:", b)); } return sb.substring(0, sb.length() - 1); } } } catch (Exception e) { e.printStackTrace(); } return "02:00:00:00:00:00"; } private static String getMacAddressByInetAddress() { try { InetAddress inetAddress = getInetAddress(); if (inetAddress != null) { NetworkInterface ni = NetworkInterface.getByInetAddress(inetAddress); if (ni != null) { byte[] macBytes = ni.getHardwareAddress(); if (macBytes != null && macBytes.length > 0) { StringBuilder sb = new StringBuilder(); for (byte b : macBytes) { sb.append(String.format("%02x:", b)); } return sb.substring(0, sb.length() - 1); } } } } catch (Exception e) { e.printStackTrace(); } return "02:00:00:00:00:00"; } private static InetAddress getInetAddress() { try { Enumeration nis = NetworkInterface.getNetworkInterfaces(); while (nis.hasMoreElements()) { NetworkInterface ni = nis.nextElement(); // To prevent phone of xiaomi return "10.0.2.15" if (!ni.isUp()) continue; Enumeration addresses = ni.getInetAddresses(); while (addresses.hasMoreElements()) { InetAddress inetAddress = addresses.nextElement(); if (!inetAddress.isLoopbackAddress()) { String hostAddress = inetAddress.getHostAddress(); if (hostAddress.indexOf(':') < 0) return inetAddress; } } } } catch (SocketException e) { e.printStackTrace(); } return null; } private static String getMacAddressByFile() { ShellUtils.CommandResult result = ShellUtils.execCmd("getprop wifi.interface", false); if (result.result == 0) { String name = result.successMsg; if (name != null) { result = ShellUtils.execCmd("cat /sys/class/net/" + name + "/address", false); if (result.result == 0) { String address = result.successMsg; if (address != null && address.length() > 0) { return address; } } } } return "02:00:00:00:00:00"; }

2.android_Id  在 Android 8.0(API 级别 26)及更高版本中,SSAID 提供了一个在由同一开发者签名密钥签名的应用之间通用的标识符。借助它,您可以在这些应用之间共享状态,而无需要求用户登录帐号。这是官网的翻译,实在不明白是什么意思!可以知道的是恢复出厂设置这个值是会被改变的,而且存在有的设备获取到的为null 的情况

    @SuppressLint("HardwareIds")
    public static String getAndroidID() {
        return Settings.Secure.getString(
                Utils.getApp().getContentResolver(),
                Settings.Secure.ANDROID_ID
        );
    }

以下内容取自:http://blog.rcant.com/2018/05/02/android/android_uuid_get/

3.The IMEI: 仅仅只对Android手机有效:

1
2
TelephonyManager TelephonyMgr = (TelephonyManager)getSystemService(TELEPHONY_SERVICE); 
String szImei = TelephonyMgr.getDeviceId();

采用此种方法,需要在AndroidManifest.xml中加入一个许可:android.permission.READ_PHONE_STATE,并且用户应当允许安装此应用。作为手机来讲,IMEI是唯一的,它应该类似于 359881030314356(除非你有一个没有量产的手机(水货)它可能有无效的IMEI,如:0000000000000)。

4.Pseudo-Unique ID, 这个在任何Android手机中都有效
有一些特殊的情况,一些如平板电脑的设置没有通话功能,或者你不愿加入READ_PHONE_STATE许可。而你仍然想获得唯一序列号之类的东西。这时你可以通过取出ROM版本、制造商、CPU型号、以及其他硬件信息来实现这一点。这样计算出来的ID不是唯一的(因为如果两个手机应用了同样的硬件以及Rom 镜像)。但应当明白的是,出现类似情况的可能性基本可以忽略。要实现这一点,你可以使用Build类:

大多数的Build成员都是字符串形式的,我们只取他们的长度信息。我们取到13个数字,并在前面加上“35”。这样这个ID看起来就和15位IMEI一样了

 

String m_szDevIDShort = "35" + //we make this look like a valid IMEI 

Build.BOARD.length()%10 + 
Build.BRAND.length()%10 + 
Build.CPU_ABI.length()%10 + 
Build.DEVICE.length()%10 + 
Build.DISPLAY.length()%10 + 
Build.HOST.length()%10 + 
Build.ID.length()%10 + 
Build.MANUFACTURER.length()%10 + 
Build.MODEL.length()%10 + 
Build.PRODUCT.length()%10 + 
Build.TAGS.length()%10 + 
Build.TYPE.length()%10 + 
Build.USER.length()%10 ; //13 digits

5.拼接生成UUID

//获取手机的唯一标识
 public String getPhoneSign(){
   StringBuilder deviceId = new StringBuilder();
   // 渠道标志
   deviceId.append("a");
   try {
    //IMEI(imei)
    TelephonyManager tm = (TelephonyManager) this.getSystemService(Context.TELEPHONY_SERVICE);
    String imei = tm.getDeviceId();
    if(!TextUtils.isEmpty(imei)){
     deviceId.append("imei");
     deviceId.append(imei);
     return deviceId.toString();
    }
    //序列号(sn)
    String sn = tm.getSimSerialNumber();
    if(!TextUtils.isEmpty(sn)){
     deviceId.append("sn");
     deviceId.append(sn);
     return deviceId.toString();
    }
    //如果上面都没有, 则生成一个id:随机码
    String uuid = getUUID();
    if(!TextUtils.isEmpty(uuid)){
     deviceId.append("id");
     deviceId.append(uuid);
     return deviceId.toString();
    }
   } catch (Exception e) {
    e.printStackTrace();
    deviceId.append("id").append(getUUID());
   }
   return deviceId.toString();
  }
/**
  * 得到全局唯一UUID
  */
 private String uuid;
 public String getUUID(){
  SharedPreferences mShare = getSharedPreferences("uuid",MODE_PRIVATE);
  if(mShare != null){
   uuid = mShare.getString("uuid", "");
  }
  if(TextUtils.isEmpty(uuid)){
   uuid = UUID.randomUUID().toString();
   mShare.edit().putString("uuid",uuid).commit();
  }
  return uuid;
 }

UUID是指在一台机器上生成的数字,它保证对在 同一时空中 的所有机器都是唯一的。通常平台会提供生成的API。按照开放软件基金会(OSF)制定的标准计算,用到了以太网卡地址、纳秒级时间、芯片ID码和许多可能的数字.

总结:个人感觉从上面的内容看,方法四 更好一些,虽然现在项目用的是mac 地址,后台要mac 给他mac 就是了,不想多BB。感觉移动端还是有点苦逼的,后台不需要了解移动端,前端更不必,但移动端却要要求懂后台和前端,还要搞jni +c 。立个flag 总有一天,前端,后台,移动端 全自己做了

你可能感兴趣的:(android)