android 设备id问题汇总 - bei1999/work GitHub Wiki

前言

经常听到某某需求提要获取设备唯一id,用途就多了,要跟踪设备,做个收藏了(看完全文你就知道这个需求并不完美实现)

IMEI

这个算是最常见的了

android 中获取imei 代码如下

/**
 * 获取手机IMEI号
 * 
 * 需要动态权限: android.permission.READ_PHONE_STATE
 */
public static String getIMEI(Context context) {
        TelephonyManager telephonyManager = (TelephonyManager) context.getSystemService(context.TELEPHONY_SERVICE);
        String imei = telephonyManager.getDeviceId();

        return imei;
    }

缺点:

  1. 需求电话包下面权限,android 6.0后需要授权(授权相关讲解可以参阅我的其android 6.0 权限管理) 用户拒绝的情况下就获取不到。
  2. android 设备很多,山寨机可能是重复的或者直接取不到。
  3. 获取的是电话包下的,也就是说需要有电话包或者说有电话功能的设备,pad没戏。

下面的系统源码说明了一切

**
     * Returns the unique device ID, for example, the IMEI for GSM and the MEID
     * or ESN for CDMA phones. Return null if device ID is not available.
     *
     * <p>Requires Permission:
     *   {@link android.Manifest.permission#READ_PHONE_STATE READ_PHONE_STATE}
     */
    public String getDeviceId() {
        try {
            ITelephony telephony = getITelephony();
            if (telephony == null)
                return null;
            return telephony.getDeviceId(mContext.getOpPackageName());
        } catch (RemoteException ex) {
            return null;
        } catch (NullPointerException ex) {
            return null;
        }
    }

Serial Number

android.os.Build.SERIAL
/** A hardware serial number, if available.  Alphanumeric only, case-insensitive. */
    public static final String SERIAL = getString("ro.serialno");

缺点:

  1. android 2.3以上,据说有些设备获取有问题

SimSerialNumber

android.telephony.TelephonyManager tm = (android.telephony.TelephonyManager) context.getSystemService(Context.TELEPHONY_SERVICE);
String simSerialNum = tm.getSimSerialNumber();

缺点:

  1. 需求电话包下面权限,android 6.0后需要授权(授权相关讲解可以参阅我的其android 6.0 权限管理) 用户拒绝的情况下就获取不到。
  2. 需要正常可用的sim卡,没卡的设备或者pad 不能获取。
  3. 跟sim卡相关,号码唯一性不能完全放心

MacAddress

android.net.wifi.WifiManager wifi = (android.net.wifi.WifiManager) context.getSystemService(Context.WIFI_SERVICE);
String macAddress = wifi.getConnectionInfo().getMacAddress();

缺点:

  1. 需要 ACCESS_WIFI_STATE 权限,android 6.0后需要授权(授权相关讲解可以参阅我的其android 6.0 权限管理) 用户拒绝的情况下就获取不到。
  2. Android 6.0 使用存在风险,google service 会提示有害程序。

ANDROID_ID

String androidId = android.provider.Settings.Secure.getString(context.getContentResolver(), android.provider.Settings.Secure.ANDROID_ID);

缺点

  1. 设备第一次启动的时候生成并保存,并且可能会在恢复出厂设置后重置该值。理论上是大部分是重置的。
  2. 跟操作系统相关,多个用户帐号,获取不同。
  3. android 设备很多,山寨机可能是重复的或者直接取不到。

总结

上面列出了一些获取到的系统id,使用还是要根据自己的情况使用,若允许用户授权操作,imei可以考虑,若不希望打扰用户,不在乎刷机等问题,可以使用android_id,极端情况可以考虑服务器产生id,下发的方式,比如做登录系统oauth 2.0等