Android-Daily-Interview icon indicating copy to clipboard operation
Android-Daily-Interview copied to clipboard

2019-10-08:如何获取Android设备唯一ID?

Open Moosphan opened this issue 5 years ago • 8 comments

Moosphan avatar Oct 08 '19 00:10 Moosphan

  1. imei 国际移动设备识别码,是第一个想到的,是手机的身份证,刷机不会被改变

缺点: 只适用于电话功能设备 不适用于pad 6.0以后需要动态申请权限 有些设备会返回错误

2.手机WiFi或蓝牙的MAC地址 缺点: 硬件限制:并不是所有的设备都有WiFi和蓝牙硬件 但其实大部分设备都是支持wifi和蓝牙的了,所以这条并不重要 如果WiFi没有打开过,是无法获取其Mac地址的(高版本获取到的mac将是固定的:02:00:00:00:00:00); 高版本好像有方法可以获取到,但也要适配一系列版本,以后变动要持续适配 https://blog.csdn.net/chaozhung_no_l/article/details/78329371 蓝牙是只有在打开的时候才能获取到其Mac地址(需要动态申请权限) **

3.Serial Number 硬件序列,在Android 2.2 以上可以通过 android.os.Build.SERIAL 获得序列号

缺点: https://stackoverflow.com/questions/11029294/android-how-to-programmatically-access-the-device-serial-number-shown-in-the-av https://developer.android.com/reference/android/os/Build.html#SERIAL

A hardware serial number, if available. Alphanumeric only, case-insensitive. For apps targeting SDK higher than Build.VERSION_CODES.O_MR1 this field is set to UNKNOWN. 硬件序列号(如果有)。 仅限字母数字,不区分大小写。 对于定位SDK高于Build.VERSION_CODES.O_MR1的应用,此字段设置为UNKNOWN。 26以后被弃用,getSerial ()替代,需要动态申请READ_PHONE_STATE权限

4.android Id 设备首次启动产生的,不需要获取权限 8.0中,只要程序包名称和签名密钥相同,ANDROID_ID值就不会在程序包卸载/重新安装时更改 获取方法: String androidId = Settings.Secure.getString(context.getContentResolver(), Settings.Secure.ANDROID_ID);

缺点: 设备恢复出厂设置会被重置 部分手机返回为空或固定值9774d56d682e549c 考虑到动态申请权限成本较高,可接受恢复出厂重置androidId 公司几部测试机从4.4 5.0 6.0 7.0 8.0 均测试以下方法能成功获取到相同androidId

经上几种比较android id方式较为可靠 最终方法如下:

private static String deviceId = null;

public static String getDeviceId() { if (!TextUtils.isEmpty(deviceId)) { return deviceId; } if (!TextUtils.isEmpty(SPUtils.getStringValue(DEVICE_ID_KEY, ""))) { //从sp中获取 deviceId = SPUtils.getStringValue(DEVICE_ID_KEY, ""); }else{ //sp中没有 String uuId; String androidId = Settings.Secure.getString(context.getContentResolver(), Settings.Secure.ANDROID_ID); if (TextUtils.isEmpty(androidId) || TextUtils.equals("9774d56d682e549c", androidId)) { uuId = UUID.randomUUID().toString(); } else { //构造UUID,防止直接暴露ANDROID_ID uuId = new UUID(androidId.hashCode(), ((long) androidId.hashCode() << 32)).toString(); } deviceId = uuId.replace("-", ""); //保存sp SPUtils.setStringValue(DEVICE_ID_KEY, deviceId); } return deviceId; }

Kebiiii avatar Oct 08 '19 01:10 Kebiiii

Android ID uuid deviceid 蓝牙或Wi-Fimac的地址 硬件和型号

gabyallen avatar Oct 08 '19 02:10 gabyallen

看需求了,如果用来做单点登录,那用应用首次安装时间足够了。 做统计类的,把首次安装时间放到卸载删不掉的地方。

Reginer avatar Oct 09 '19 01:10 Reginer

  1. imei 国际移动设备识别码,是第一个想到的,是手机的身份证,刷机不会被改变

缺点: 只适用于电话功能设备 不适用于pad 6.0以后需要动态申请权限 有些设备会返回错误

2.手机WiFi或蓝牙的MAC地址 缺点: 硬件限制:并不是所有的设备都有WiFi和蓝牙硬件 但其实大部分设备都是支持wifi和蓝牙的了,所以这条并不重要 如果WiFi没有打开过,是无法获取其Mac地址的(高版本获取到的mac将是固定的:02:00:00:00:00:00); 高版本好像有方法可以获取到,但也要适配一系列版本,以后变动要持续适配 https://blog.csdn.net/chaozhung_no_l/article/details/78329371 蓝牙是只有在打开的时候才能获取到其Mac地址(需要动态申请权限) **

3.Serial Number 硬件序列,在Android 2.2 以上可以通过 android.os.Build.SERIAL 获得序列号

缺点: https://stackoverflow.com/questions/11029294/android-how-to-programmatically-access-the-device-serial-number-shown-in-the-av https://developer.android.com/reference/android/os/Build.html#SERIAL

A hardware serial number, if available. Alphanumeric only, case-insensitive. For apps targeting SDK higher than Build.VERSION_CODES.O_MR1 this field is set to UNKNOWN. 硬件序列号(如果有)。 仅限字母数字,不区分大小写。 对于定位SDK高于Build.VERSION_CODES.O_MR1的应用,此字段设置为UNKNOWN。 26以后被弃用,getSerial ()替代,需要动态申请READ_PHONE_STATE权限

4.android Id 设备首次启动产生的,不需要获取权限 8.0中,只要程序包名称和签名密钥相同,ANDROID_ID值就不会在程序包卸载/重新安装时更改 获取方法: String androidId = Settings.Secure.getString(context.getContentResolver(), Settings.Secure.ANDROID_ID);

缺点: 设备恢复出厂设置会被重置 部分手机返回为空或固定值9774d56d682e549c 考虑到动态申请权限成本较高,可接受恢复出厂重置androidId 公司几部测试机从4.4 5.0 6.0 7.0 8.0 均测试以下方法能成功获取到相同androidId

经上几种比较android id方式较为可靠 最终方法如下:

private static String deviceId = null;

public static String getDeviceId() { if (!TextUtils.isEmpty(deviceId)) { return deviceId; } if (!TextUtils.isEmpty(SPUtils.getStringValue(DEVICE_ID_KEY, ""))) { //从sp中获取 deviceId = SPUtils.getStringValue(DEVICE_ID_KEY, ""); }else{ //sp中没有 String uuId; String androidId = Settings.Secure.getString(context.getContentResolver(), Settings.Secure.ANDROID_ID); if (TextUtils.isEmpty(androidId) || TextUtils.equals("9774d56d682e549c", androidId)) { uuId = UUID.randomUUID().toString(); } else { //构造UUID,防止直接暴露ANDROID_ID uuId = new UUID(androidId.hashCode(), ((long) androidId.hashCode() << 32)).toString(); } deviceId = uuId.replace("-", ""); //保存sp SPUtils.setStringValue(DEVICE_ID_KEY, deviceId); } return deviceId; }

双卡手机imei有两个怎么办?获取的是哪个

messi-wpy avatar Oct 15 '19 14:10 messi-wpy

双卡手机imei有两个怎么办?获取的是哪个

高版本用这个方法多个IMEI: @RequiresApi(api = Build.VERSION_CODES.LOLLIPOP_MR1) public void getSimInfoBySubscriptionManager(Context context) { List<SubscriptionInfo> list = SubscriptionManager.from(context).getActiveSubscriptionInfoList(); for (SubscriptionInfo info : list) { Log.d("Q_M", "ICCID-->" + info.getIccId()); Log.d("Q_M", "subId-->" + info.getSubscriptionId()); Log.d("Q_M", "DisplayName-->" + info.getDisplayName()); Log.d("Q_M", "CarrierName-->" + info.getCarrierName()); Log.d("Q_M", "---------------------------------"); } }

低版本用反射获取:

private void getAPI19SimInfo(Context context) { Class<?> tm = null; try { tm = Class.forName("android.telephony.MSimTelephonyManager");

        Method getSubscriberIdMethod = tm.getMethod("getSubscriberId", int.class);
        Method getSimSerialNumberMethod = tm.getMethod("getSimSerialNumber", int.class);

        Object service = context.getSystemService("phone_msim");

        //0 代表卡1
        //1 代表卡2
        String s = (String) getSimSerialNumberMethod.invoke(service, 0);
        Log.d("Q_M", "-->" + s);

    } catch (ClassNotFoundException e) {
        e.printStackTrace();
    } catch (NoSuchMethodException e) {
        e.printStackTrace();
    } catch (InvocationTargetException e) {
        e.printStackTrace();
    } catch (IllegalAccessException e) {
        e.printStackTrace();
    }
}

参考:https://blog.csdn.net/niyingxunzong/article/details/77188040

Kebiiii avatar Oct 16 '19 01:10 Kebiiii

常用方法: IMEI 权限(读手机权限) 可以手动更改(模拟器上) /关闭权限报错

Mac地址 访问WIFI权限 有些设备没有wifi(没有上网功能)/6.0以上版本返回的都是固定的02:00:00 之类地址

ANDROID_ID 设备首次运行,系统会随机生成一个64位的数字,转换成16进制保存 手机恢复出厂设置后值有变化/ 有些国产设备不会返回值

Serial Number (设备序列号) 有些国产手机(红米)会出现垃圾数据

实现思路: 1.获取设备的IMEI -->设备的Mac地址-->随机生成的UUID, 2.拼接在一起,然后用MD5加密 3.存储到本地的文件中,隐藏. 并且存储在App中的sp中 4.使用的时候先从sp中读取, 没有的再生成,然后把生成的唯一id保存到sp中

xiaoxianBoy avatar Oct 17 '19 13:10 xiaoxianBoy

IMEI ANDROIDID UUID

mlinqirong avatar Jan 10 '22 08:01 mlinqirong

IMEI ANDROIDID UUID

mlinqirong avatar Jan 10 '22 08:01 mlinqirong