Android获唯一标识

Android开发中有时候因业务需要客户端要产生一个唯一的标识符使服务器能识别某台Android设备,目前一般使用三种标识符分别为 DeviceId 、 AndroidId 、 MAC地址 。

获取DeviceId

在获取deviceId之前先要要 AndroidManifest 中声明权限:

<uses-permission android:name="android.permission.READ_PHONE_STATE" />

通过以下代码获取DeviceId:

    public static String getDeviceId(Context context){
        String  deviceId = null;
        if(ContextCompat.checkSelfPermission(context, Manifest.permission.READ_PHONE_STATE) == PackageManager.PERMISSION_GRANTED) {
            TelephonyManager tm = (TelephonyManager) context.getSystemService(Context.TELEPHONY_SERVICE);
            deviceId = tm.getDeviceId();
        }
        return deviceId;
    }

在获取设备ID时应该注意:

  • 需要 READ_PHONE_STATE 权限
  • 在6.0或更高的设备上时因为权限要在运行时请求而 READ_PHONE_STATE 是一个dangerous 权限用户极有可能不允许这个权限请求

获取AndroidId

获取AndroidId是不需要权限的但是AndroidId是可能变的,AndroidId是在用户第一次激活这个设备时产生的所以当用户重置手机时AndroidId会产生变化,理论上这个AndroidId是可以接受的毕竟重置手机这个事发生也不会太频繁。

获取AndroidId:

 public static String    getAndroidId(Context context){
        return Settings.Secure.getString(context.getContentResolver(), Settings.Secure.ANDROID_ID);
    }

获取MAC地址

可以使用WIFI的MAC地址来作为标识符,感觉现阶段这种方式比较可靠总结如下:

  • Mac地址是唯一的
  • 直接产生在硬件上基本上不会变更
  • 不需要额外的权限
  • 向上或向下兼容
    public static String getMacAddress(Context context) {
        String macAddress = null;
        try{
            String wifiInterfaceName = "wlan0";
            Enumeration<NetworkInterface> interfaces = NetworkInterface.getNetworkInterfaces();
            while (interfaces.hasMoreElements()) {
                NetworkInterface iF = interfaces.nextElement();
                if(iF.getName().equalsIgnoreCase(wifiInterfaceName)) {
                    byte[] addr = iF.getHardwareAddress();
                    if (addr == null || addr.length == 0) {
                        return null;
                    }

                    StringBuilder buf = new StringBuilder();
                    for (byte b : addr) {
                        buf.append(String.format("%02X:", b));
                    }
                    if (buf.length() > 0) {
                        buf.deleteCharAt(buf.length() - 1);
                    }
                    macAddress =  buf.toString();
                    break;
                }
            }
        }catch (SocketException se){
            macAddress = null;
        }

        if(TextUtils.isEmpty(macAddress)){
            android.net.wifi.WifiManager wifi = (android.net.wifi.WifiManager) context.getSystemService(Context.WIFI_SERVICE);
            macAddress = wifi.getConnectionInfo().getMacAddress();
        }

        return macAddress;
    }

使用Android自带的API时有个坑WifiInfo里面有这样一段代码:

   /**
     * Default MAC address reported to a client that does not have the
     * android.permission.LOCAL_MAC_ADDRESS permission.
     *
     * @hide
     */
    public static final String DEFAULT_MAC_ADDRESS = "02:00:00:00:00:00";

上面的代码是从6.0API复制出来的意思是说如果你没有说明android.permission.LOCAL_MAC_ADDRESS 权限那么将返回这个默认的MAC地址我在6.0上的机器上试了一下好像并没有像它说的那样我声明android.permission.LOCAL_MAC_ADDRESS 仅限后还是拿到这个默认的MAC地址。也没有继续深究发现通过JAVA的API也是可以使到MAC地址的。

原文地址:https://www.cnblogs.com/exmyth/p/5327012.html