Android 各个版本获取IMEI、MEID

您所在的位置:网站首页 小米平板5怎么查看imei Android 各个版本获取IMEI、MEID

Android 各个版本获取IMEI、MEID

2023-11-24 09:11| 来源: 网络整理| 查看: 265

MEID/IMEI1/IMEI2 (可通过在手机拨号键盘中输入 *#06# 即可查询)

IMEI:(International Mobile Equipment Identity)国际移动设备身份码的缩写,由15~17(中国基本都15)位数字组成的电子串号与每台手机一一对应,且该码全世界唯一。

MEID:(Mobile Equipment Identifier)移动设备识别码,是CDMA手机的身份识别码,也是每台CDMA手机或通讯平板唯一的识别码,由14位数字组成。

在中国 移动卡和联通卡使用的是GSM制式 即使用IMEI , 电信卡使用CDMA制式 即使用MEID

Android个版本获取MEID/IMEI情况 版本 = 版本 < 8 的系统如果想获取MEID/IMEI1/IMEI2 ---- 可以通过 getDeviceId() 获取8.0 //优先获取IMEI(即使是电信卡) 不行的话就获取MEID return getImeiOrMeid(context, 0); } /** * 获取imei2 * * @param context * @return */ public static String getIMEI2(Context context) { //imei2必须与 imei1不一样 String imeiDefault = getIMEI1(context); if (TextUtils.isEmpty(imeiDefault)) { //默认的 imei 竟然为空,说明权限还没拿到,或者是平板 //这种情况下,返回 imei2也应该是空串 return ""; } //注意,拿第一个 IMEI 是传0,第2个 IMEI 是传1,别搞错了 String imei1 = getImeiOrMeid(context, 0); String imei2 = getImeiOrMeid(context, 1); //sim 卡换卡位时,imei1与 imei2有可能互换,而 imeidefault 有可能不变 if (!TextUtils.equals(imei2, imeiDefault)) { //返回与 imeiDefault 不一样的 return imei2; } if (!TextUtils.equals(imei1, imeiDefault)) { return imei1; } return ""; } /** * 获取 Imei/Meid 优先获取IMEI(即使是电信卡) 不行的话就获取MEID *

* 如果装有CDMA制式的SIM卡(电信卡) ,在Android 8 以下 只能获取MEID ,无法获取到该卡槽的IMEI * 8及以上可以通过 #imei 方法获取IMEI 通过 #deviceId 方法获取的是MEID * * @param context * @param slotId slotId为卡槽Id,它的值为 0、1; * @return */ public static String getImeiOrMeid(Context context, int slotId) { String imei = ""; //Android 6.0 以后需要获取动态权限 检查权限 if (ContextCompat.checkSelfPermission(context, Manifest.permission.READ_PHONE_STATE) != PackageManager.PERMISSION_GRANTED) { return imei; } try { TelephonyManager manager = (TelephonyManager) context.getApplicationContext().getSystemService(Context.TELEPHONY_SERVICE); if (manager != null) { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {// android 8 即以后建议用getImei 方法获取 不会获取到MEID Method method = manager.getClass().getMethod("getImei", int.class); imei = (String) method.invoke(manager, slotId); } else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { //5.0的系统如果想获取MEID/IMEI1/IMEI2 ----framework层提供了两个属性值“ril.cdma.meid"和“ril.gsm.imei"获取 imei = getSystemPropertyByReflect("ril.gsm.imei"); //如果获取不到 就调用 getDeviceId 方法获取 } else {//5.0以下获取imei/meid只能通过 getDeviceId 方法去取 } } } catch (Exception e) { } if (TextUtils.isEmpty(imei)) { imei = getDeviceId(context, slotId); } return imei; } /** * 仅获取 Imei 如果获取到的是meid 或空 均返回空字符串 * * @param slotId slotId为卡槽Id,它的值为 0、1; * @return */ public static String getImeiOnly(Context context, int slotId) { String imei = ""; //Android 6.0 以后需要获取动态权限 检查权限 if (ContextCompat.checkSelfPermission(context, Manifest.permission.READ_PHONE_STATE) != PackageManager.PERMISSION_GRANTED) { return imei; } try { TelephonyManager manager = (TelephonyManager) context.getApplicationContext().getSystemService(Context.TELEPHONY_SERVICE); if (manager != null) { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {// android 8 即以后建议用getImei 方法获取 不会获取到MEID Method method = manager.getClass().getMethod("getImei", int.class); imei = (String) method.invoke(manager, slotId); } else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { //5.0的系统如果想获取MEID/IMEI1/IMEI2 ----framework层提供了两个属性值“ril.cdma.meid"和“ril.gsm.imei"获取 imei = getSystemPropertyByReflect("ril.gsm.imei"); //如果获取不到 就调用 getDeviceId 方法获取 } else {//5.0以下获取imei/meid只能通过 getDeviceId 方法去取 } } } catch (Exception e) { } if (TextUtils.isEmpty(imei)) { String imeiOrMeid = getDeviceId(context, slotId); //长度15 的是imei 14的是meid if (!TextUtils.isEmpty(imeiOrMeid) && imeiOrMeid.length() >= 15) { imei = imeiOrMeid; } } return imei; } /** * 仅获取 Meid 如果获取到的是imei 或空 均返回空字符串 * 一般只有一个 meid 即获取到的二个是相同的 * * @param context * @param slotId slotId为卡槽Id,它的值为 0、1; * @return */ public static String getMeidOnly(Context context, int slotId) { String meid = ""; //Android 6.0 以后需要获取动态权限 检查权限 if (ContextCompat.checkSelfPermission(context, Manifest.permission.READ_PHONE_STATE) != PackageManager.PERMISSION_GRANTED) { return meid; } try { TelephonyManager manager = (TelephonyManager) context.getApplicationContext().getSystemService(Context.TELEPHONY_SERVICE); if (manager != null) { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {// android 8 即以后建议用getMeid 方法获取 不会获取到Imei Method method = manager.getClass().getMethod("getMeid", int.class); meid = (String) method.invoke(manager, slotId); } else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { //5.0的系统如果想获取MEID/IMEI1/IMEI2 ----framework层提供了两个属性值“ril.cdma.meid"和“ril.gsm.imei"获取 meid = getSystemPropertyByReflect("ril.cdma.meid"); //如果获取不到 就调用 getDeviceId 方法获取 } else {//5.0以下获取imei/meid只能通过 getDeviceId 方法去取 } } } catch (Exception e) { } if (TextUtils.isEmpty(meid)) { String imeiOrMeid = getDeviceId(context, slotId); //长度15 的是imei 14的是meid if (imeiOrMeid.length() == 14) { meid = imeiOrMeid; } } return meid; } private static String getSystemPropertyByReflect(String key) { try { @SuppressLint("PrivateApi") Class clz = Class.forName("android.os.SystemProperties"); Method getMethod = clz.getMethod("get", String.class, String.class); return (String) getMethod.invoke(clz, key, ""); } catch (Exception e) {/**/} return ""; } /** * 获取 IMEI/MEID * * @param context 上下文 * @return 获取到的值 或者 空串"" */ public static String getDeviceId(Context context) { String imei = ""; //Android 6.0 以后需要获取动态权限 检查权限 if (ContextCompat.checkSelfPermission(context, Manifest.permission.READ_PHONE_STATE) != PackageManager.PERMISSION_GRANTED) { return imei; } // 1. 尝试通过系统api获取imei imei = getDeviceIdFromSystemApi(context); if (TextUtils.isEmpty(imei)) { imei = getDeviceIdByReflect(context); } return imei; } /** * 获取 IMEI/MEID * * @param context 上下文 * @param slotId slotId为卡槽Id,它的值为 0、1; * @return 获取到的值 或者 空串"" */ public static String getDeviceId(Context context, int slotId) { String imei = ""; // 1. 尝试通过系统api获取imei imei = getDeviceIdFromSystemApi(context, slotId); if (TextUtils.isEmpty(imei)) { imei = getDeviceIdByReflect(context, slotId); } return imei; } /** * 调用系统接口获取 IMEI/MEID *

* Android 6.0之后如果用户不允许通过 {@link Manifest.permission#READ_PHONE_STATE} 权限的话, * 那么是没办法通过系统api进行获取 IMEI/MEID 的,但是可以通过{@linkplain #getDeviceIdByReflect(Context)} 反射}绕过权限进行获取 * * @param context 上下文 * @return 获取到的值 或者 空串"" */ public static String getDeviceIdFromSystemApi(Context context, int slotId) { String imei = ""; try { TelephonyManager telephonyManager = (TelephonyManager) context.getApplicationContext().getSystemService(Context.TELEPHONY_SERVICE); if (telephonyManager != null) { imei = telephonyManager.getDeviceId(slotId); } } catch (Throwable e) { } return imei; } public static String getDeviceIdFromSystemApi(Context context) { String imei = ""; try { TelephonyManager telephonyManager = (TelephonyManager) context.getApplicationContext().getSystemService(Context.TELEPHONY_SERVICE); if (telephonyManager != null) { imei = telephonyManager.getDeviceId(); } } catch (Throwable e) { } return imei; } /** * 反射获取 IMEI/MEID *

* Android 6.0之后如果用户不允许通过 {@link Manifest.permission#READ_PHONE_STATE} 权限的话, * 那么是没办法通过系统api进行获取 IMEI/MEID 的,但是可以通过这个反射来尝试绕过权限进行获取 * * @param context 上下文 * @return 获取到的值 或者 空串"" */ public static String getDeviceIdByReflect(Context context) { try { TelephonyManager tm = (TelephonyManager) context.getApplicationContext().getSystemService(Context.TELEPHONY_SERVICE); if (Build.VERSION.SDK_INT >= 21) { Method simMethod = TelephonyManager.class.getDeclaredMethod("getDefaultSim"); Object sim = simMethod.invoke(tm); Method method = TelephonyManager.class.getDeclaredMethod("getDeviceId", int.class); return method.invoke(tm, sim).toString(); } else { Class clazz = Class.forName("com.android.internal.telephony.IPhoneSubInfo"); Method subInfoMethod = TelephonyManager.class.getDeclaredMethod("getSubscriberInfo"); subInfoMethod.setAccessible(true); Object subInfo = subInfoMethod.invoke(tm); Method method = clazz.getDeclaredMethod("getDeviceId"); return method.invoke(subInfo).toString(); } } catch (Throwable e) { } return ""; } /** * 反射获取 deviceId * * @param context * @param slotId slotId为卡槽Id,它的值为 0、1; * @return */ public static String getDeviceIdByReflect(Context context, int slotId) { try { TelephonyManager tm = (TelephonyManager) context.getApplicationContext().getSystemService(Context.TELEPHONY_SERVICE); Method method = tm.getClass().getMethod("getDeviceId", int.class); return method.invoke(tm, slotId).toString(); } catch (Throwable e) { } return ""; } } Demo示例:

对于8.0以下系统(卡1:移动/联通,卡2:电信)

* getIMEI1 = imei1 * getIMEI2 = meid / imei 基本都是meid * getImeiOnly(0) = imei1 * getImeiOnly(1) =imei2 / null * getMeidOnly(0) = meid / null * getMeidOnly(1) = meid / null * getImeiOrMeid(0) = imei1 * getImeiOrMeid(1) = meid / imei 基本都是meid * getDeviceId(0) = imei1 * getDeviceId(1) = meid / imei 基本都是meid

对于8.0及以上 10以下系统 (卡1:移动/联通,卡2:电信)

* getIMEI1 = imei1 * getIMEI2 = imei2 * getImeiOnly(0) = imei1 * getImeiOnly(1) =imei2 * getMeidOnly(0) = meid * getMeidOnly(1) = meid * getImeiOrMeid(0) = imei1 * getImeiOrMeid(1) = imie2 * getDeviceId(0) = imei1 * getDeviceId(1) = imei2

区别在于 8.0以下 getDeviceId() 会根据SIM卡获取对应设备id,当为不插卡或者移动、联通卡时,返回imei;当插电信卡,返回meid。 8.0以上 时,可以用getImei() 和 getMeid() 方法准确的获取对应的 参数。

有些人在开发时遇到 同一个方法 在不同系统版本 或 不同SIM卡 时获取值不一样时也是这个原因,可以自己尝试下找不同手机试试。

其他设备ID

除了IMEI/MEID这些外还有部分id可以尝试获取

android_id String andoirdID =Settings.Secure.getString(context.applicationContext.contentResolver, Settings.Secure.ANDROID_ID )

注意:部分设备AndroidId可能为空 或者 多台设备AndroidId可能相同

oaid (不了解的可以自己查下)

//需要去移动安全联盟AMS 申请对应的SDK,文档对接 http://www.msa-alliance.cn/col.jsp?id=120

这里有我下载好的,已经上传 https://download.csdn.net/download/MirkoWug/12737761 也可以直接用这个、



【本文地址】


今日新闻


推荐新闻


CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3