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情况

  • 版本 <= 4.x 如果想获取MEID/IMEI1/IMEI2 ----其实是很难做到的。 因为你只能只用getDeviceId() 这个方法
  • 版本 = 5.x 的系统如果想获取MEID/IMEI1/IMEI2 ----framework层提供了两个属性值“ril.cdma.meid"和“ril.gsm.imei"获取meid、imei1、imei2(必须使用反射方法) 也可以用getDeviceId()获取
  • 6.0 >= 版本 < 8 的系统如果想获取MEID/IMEI1/IMEI2 ---- 可以通过 getDeviceId() 获取
  • 8.0 <= 版本 <10 可以通过个getMeid/getImei 优先获取对应值 也可以通过 getDeviceId() 获取
  • 版本 >= 10 系统API限制,无法获取到imei/meid 以上方法均无效

注意:
getDeviceId(): 能获取到imei 或 meid ,会根据插得卡返回对应值,不插卡或插移动联通卡默认返回imei 插电信卡则返回meid
getMeid():8.0及以后调用 返回meid
getImei():8.0及以后调用 返回imei

工具类

 public class IMEIUtil {/*** 获取默认的imei  一般都是IMEI 1** @param context* @return*/public static String getIMEI1(Context context) {//优先获取IMEI(即使是电信卡)  不行的话就获取MEIDreturn 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* <p>* 如果装有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 方法获取 不会获取到MEIDMethod 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 方法获取 不会获取到MEIDMethod 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的是meidif (!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 方法获取 不会获取到ImeiMethod 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的是meidif (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获取imeiimei = 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获取imeiimei = getDeviceIdFromSystemApi(context, slotId);if (TextUtils.isEmpty(imei)) {imei = getDeviceIdByReflect(context, slotId);}return imei;}/*** 调用系统接口获取 IMEI/MEID* <p>* 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* <p>* 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 也可以直接用这个、

Android 各个版本获取IMEI、MEID相关推荐

  1. android 获取 meid 代码,Android 各个版本获取IMEI、MEID

    public class IMEIUtil { /** * 获取默认的imei 一般都是IMEI 1 * * @param context * @return */ public static Str ...

  2. Android多个imei如何获取,如何在Android 10中获取IMEI号,这是获取在Android 10及以下Android 10中获取IMEI号的代码...

    如何在android 10中获取imei编号,这是获取在android 10及以下android 10中获取imei编号的代码. if (android.os.Build.VERSION.SDK_IN ...

  3. Android中如何获取IMEI号码

    首先刚看见这个需求,觉得有病吧.没办法也得解决.以下方法亲测有效,希望能帮助到大家. 首先我们应该注意的是需要一个权限,要不怎么都不会成功的 <uses-permission android:n ...

  4. imei ios android,ios设备获取IMEI

    ios设备获取IMEI [2021-01-28 02:25:52]  简介: php去除nbsp的方法:首先创建一个PHP代码示例文件:然后通过"preg_replace("/(\ ...

  5. android系统如何获取imei号码,获取手机型号和系统版本号

    2.tm.CALL_STATE_RINGING=1 响铃 3.tm.CALL_STATE_OFFHOOK=2 摘机 */ tm.getCallState();//int /* 电话方位: */ tm. ...

  6. 如何查看手机的android版本号,android系统如何获取imei号码,获取手机型号和系统版本号...

    核心代码: Imei = ((TelephonyManager) getSystemService(TELEPHONY_SERVICE)) .getDeviceId(); 1.加入权限 在manife ...

  7. caf格式 android,实例:Android Studio3+版本 获取存有ANR信息的traces.txt文件,解决ANR问题...

    一.前期基础知识储备 traces.txt系统自动生成的记录anr等异常的文件,只记录java代码产生的异常. 如果是旧版本(Android Studio3以下的版本)的AS,可以直接通过DDMS的F ...

  8. 【记录】 Android 双卡手机获取IMEI等

    1.前言 项目中遇到上传手机imei的问题.如果手机是双卡,目前只能获取默认的imei TelephonyManager mTelephonyMgr = (TelephonyManager) getS ...

  9. android获取imei(android获取wifi密码)

    android系统如何获取imei号码,获取手机型号和系统版本号 /*****创建日期2010-4-29下午05:02:47**/packagenet.sunniwell.app;importandr ...

最新文章

  1. gpu的单位表示_GPU编程1--GPU中的基本概念
  2. Linux RedHat7.0 上vsftp配置
  3. Reflection.Emit的使用场景、工具包及示例总结
  4. nginx.conf删除与否网页都能访问(nginx没有生效)的问题
  5. ffmpeg相关资源
  6. IO、NIO、AIO
  7. Python最快的方式来读取大文本文件(几GB)
  8. Window环境下使用C#调用VBScript、JavaScript等脚本
  9. GJB 软件定型测评报告(模板)
  10. 鸿蒙汽车电动尾门工厂,汽车智能电动尾门为什么能成为汽车电子行业“新宠”?...
  11. Ubuntu过去十年的10个关键时刻
  12. 卡特兰数 史上最全最详细讲解!
  13. 大数据十年:Cloudera向左,Palantir向右
  14. java实现面向对象的23种设计模式【超长预警,读完超过2小时】
  15. 软件著作权转让的流程是怎么样的
  16. 菜鸟温习python爬虫
  17. windows中如何给程序添加管理权限和添加数据保护(dep)
  18. 时间序列分析的基本思路与步骤
  19. 计算机配置好坏怎么看,怎么看电脑配置,电脑配置好坏信息一目了然-腾讯电脑管家...
  20. Spring Boot使用Servlet居然也可以实现长轮询,敲了5年代码,我居然不知道 - 第413篇

热门文章

  1. 亚马逊A9算法是什么?有什么作用?(案例详解)
  2. 某个袁 对 TypeScript 索引签名 理解
  3. 合天实验室:渗透测试项目一
  4. 12306 Bug:同一张身份证,买了同一车次的两张票
  5. 用正则表达式来解释为什么你在游戏里骂人总是会显示“ **你个大** ”
  6. A-Star算法探索和实现(一)
  7. scala学习十三 开发twitter客户端
  8. 支付宝支付快速集成实现
  9. L3-008. 喊山
  10. win10html怎么创建后打不开,Win10打不开路由器设置页面(设置界面)怎么办?