原文地址:http://blog.csdn.net/ymcl_hx/article/details/53484797

近期公司下发了新任务,需要对Android手机进行双sim卡的管控,而这个功能的关键在于的准确的获取sim卡的SubscriberId值,做过sim卡相关或者电话功能的工程师会很清楚,Android SDK提供了一个方法来获取sim卡的getSubscriberId值。可是这只能获取其中主卡的id值,而副卡根本没有提供API,而且国内的手机大多是双卡手机,所以笔者花了很大功夫调研了大部分市场的畅销Android手机的双卡功能。

整个功能比较繁琐,所以一共分上下两部分讲述。上部讲述市场上主流手机获取副卡Id的方法,以及遇到的困难,注意事项;下部讲述如何整合所有的方案,实现机型自适配,提供一个稳定的API,供其他程序使用。

原生的Android是不支持双卡双待功能的,所以Android sdk没有提供API,直到在Android6.0+上增加了相关的API,但是国内的android嘛,有6.0和没6.0没啥区别,碎片化导致只能利用另外一种方法去获取了—反射。关于反射相关的知识,这里就不进行讲解了,因为获取副卡id会用到大量的反射,不懂的读者可以学习这篇博文[http://www.cnblogs.com/lzq198754/p/5780331.html。]

先说说最困难的地方吧,国内的双卡功能是由厂商联合芯片开发商定做的,所以芯片商不一样,厂商不一样,实现方案也就不一样,所以反射的类和函数名也不一样。总的来说,目前全球有高通(小米),联发科(魅族),麒麟海思(华为),猎户座(三星)四家移动通讯芯片制造商,笔者通过一周的时间,将公司的所有测试机进行了反射获取,终于总结出了如下方案:

  • 高通系: 
    代表手机:小米,vivo,oppo 
    反射的类:TelephonyManager 
    反射方法:getSubscriberId(int id) 
    反射方法:getSubscriberId(long id)

    高通系手机获取副卡的API还算规范化,直接在android的原生类中添加了方法,而android6.0+提供的官方双卡API也是这样做的。android提供获取simid原生单卡API为:

TelephonyManager telephonyManager = (TelephonyManager)getSystemService(Context.TELEPHONY_SERVICE);
String id = telephonyManager.getSubscriberId();

所以部分厂商直接在TelephonyManager类中重载了该方法, 不过厂商的重载的参数不同,比如笔者在进行开发时发现,小米,红米系列使用的重载方法为getSubscriberId(int id),而vivo,oppo,中兴则使用getSubscriberId(long id),反射的代码如下:

public int getSecondImsi(Context context) throws InvocationTargetException,IllegalAccessException, NoSuchMethodException {TelephonyManager telephonyManager = (TelephonyManager) context.getSystemService(Context.TELEPHONY_SERVICE);Class<?> telephonyclass = telephonyManager.getClass();Method method = null;boolean param = true;try {method = telephonyclass.getDeclaredMethod("getSubscriberId",int.class);}catch (NoSuchMethodException e){try {method = telephonyclass.getDeclaredMethod("getSubscriberId",long.class);param = false;}catch (NoSuchMethodException e2) {}}Object object = null;HashSet<String> buildSet = new HashSet<>();if (param){for(int i = 0;i < 9;i++) {object = method.invoke(telephonyManager,i);if (object != null){buildSet.add(object.toString());}}}return 0;}

这里需要做几点说明: 
1.反射需要抛出几种异常情况如: 
NoSuchMethodException: 没有这个函数 
IllegalAccessException:此方法为私有方法,不能反射 
InvocationTargetException:反射方法内部出现异常 
ClassNotFoundException:没有这个类,在华为系手机中会用到

2.使用HashSet保存结果,这里使用set保存结果的原因有2点 
第一是因为厂商问题,系统不会给你准确的返回卡槽1或者卡槽2的值,而是一旦判定卡槽里有卡就会返回,比如,一张卡插在任意一个卡槽中,通过系统API都能返回SIMid。所以,在插入双卡的情况下,通过反射可能会获取到所有的值,我们没有办法根据卡槽来获取值,保证卡与卡槽的一一对应。这样只能采用set的唯一性来保证获取到所有的值。

第二还是因为厂商原因,笔者在开发时发现,通过反射getSubscriberId(long id)方法,这里的参数id没有任何可参考性,当初以为可以输入0,1就能返回不同的simid,结果是输入5才能获取另一个simid……而且,就拿vivo的一款旗舰机而言,输入从1-9,只有输入5才获取到副卡的id,其他返回的都是主卡的id,这就很坑了,所有笔者简单粗暴的使用for循环,不管有没有值,都存到set里,性能会影响,但保证功能。总结一句话,厂商提供的getSubscriberId(long id)方法的id没有参考意义,直接简单粗暴的循环,这也导致了笔者实现的此功能的缺陷:只能获取到simid,没有办法保证卡与卡槽的一一对应

  • 华为系 
    代表手机:华为荣耀系列,P系列,mate系列 
    反射类:”android.telephony.MSimTelephonyManager” 
    反射方法:getSubscriberId(int id) 
    反射方法:getSubscriberId(long id)

华为系手机比较复杂,因为和自身的芯片有关系,比如,大部分华为高端机型使用了自身的芯片,第二张sim卡的相关API封装在android.telephony.MSimTelephonyManager这个类,而部分采用高通机型的华为手机还是使用高通方案。比如华为P7,P8,P9用了自身方案,而MATE8采用了高通方案,笔者在后期适配时被整的很惨…… 
要反射华为系手机的MSimTelephonyManager类的方法如下:

protected int getassistantImsi(Context context) throws IllegalAccessException, InvocationTargetException, ClassNotFoundException, NoSuchMethodException {Class<?> telephonyClass = Class.forName("android.telephony.MSimTelephonyManager");Method getdefault = telephonyClass.getMethod("getDefault");Object telephonyManager = getdefault.invoke(null);Method method = null;boolean param = true;try {method = telephonyClass.getMethod("getSubscriberId", int.class);} catch (NoSuchMethodException e) {try {method = telephonyClass.getMethod("getSubscriberId", long.class);param = false;} catch (NoSuchMethodException e2) {return NO_SUCH_METHOD;}}Object object = null;HashSet<String> buildSet = new HashSet<>();if (param) {for (int i = 0; i < 9; i++) {object = method.invoke(telephonyManager, i);if (object != null) {buildSet.add(object.toString());}}} else {for (long i = 0; i < 9; i++) {object = method.invoke(telephonyManager, i);if (object != null) {buildSet.add(object.toString());}}}return SUCCESS;}

代码与上文中高通系手机反射方案差不多,不同的是增加了一个反射类的处理

// 通过包名获取此类
Class<?> telephonyClass = Class.forName("android.telephony.MSimTelephonyManager");
//通过Class基类的getDefault方法获取此类的实例
Method getdefault = telephonyClass.getMethod("getDefault");
Object telephonyManager = getdefault.invoke(null);
Method method = null;

这样我们就能获取到类的实例,然后反射去执行就行了,其他操作如上文。

  • 三星系 
    代表手机:note2,3,s4 
    反射类:无 
    反射方法:无

早期的三星系使用的是自家的方案,如note2,3,s4等,三星也和华为一样,另外封装了一个类来管理副卡,而近期的高端机型貌似使用了android原生双卡管理,就是高通方案。 
代码如下:

TelephonyManager telephonyManager = (TelephonyManager) context.getSystemService("phone2");telephonyManager.getSubscriberId()

个人觉得另外封装一个类是比较好的处理……

  • 联发科系: 
    代表手机:魅族 
    反射类:TelephonyManager 
    反射方法:getSubscriberIdGemini()

反射方案和高通类似,就是反射的方法不同,这里就不贴代码了……

  • 其他手机: 
    展讯,MTK

其他手机反射方案也不写了,因为笔者找遍公司所有测试机,没有找到这些山寨机 
不过要适配这些机型的,可以这个博文 
http://blog.csdn.net/zc0727/article/details/15541289

结束语: 
这是笔者第一次写博文,所以写的不好请多包含,有什么问题或者错误请指正,互相进步嘛。 
欢迎转载,请指明出处。 
关于双卡功能的管理,本文只是对市场上android手机双卡的一次普查,以及方案的提供。目前是市场上存在的机型大多使用这些方法,而且网上也有很多相关博客。所以如何适配机型,根据机型来选择正确的方案,这才是实现的难点。采用人为枚举是一个很傻叉的行为(因为笔者早期的方案就是枚举所有机型),适配的工作,应该交给软件自身来做。所以,下一篇博文会讲述如何整和这些方案,让程序自行进行适配,选择合适的方案获取simid。相关代码会在下一博文中提供开源地址。

Android双卡手机:获取主卡副卡的simid(上)方案实现相关推荐

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

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

  2. 【记录】 Android 双卡手机获取两个IMEI等

    1.前言 项目中遇到上传手机imei的问题.如果手机是双卡,目前只能获取默认的imei [java] view plain copy     TelephonyManager mTelephonyMg ...

  3. 关于android双卡手机sim卡信息采集适配的心得

    关于android双卡手机sim卡信息采集适配的心得 这几天通过对各个厂商的双卡信息适配的研究,总结了几点规律,写这篇心得主要是为了能够抛砖引玉,和大家一起分享,一起讨论,源码已上传. 一.andro ...

  4. 关于android各种双卡手机获取imei,imsi的处置(mtk,展讯,高通等)

    2019独角兽企业重金招聘Python工程师标准>>> 关于android各种双卡手机获取imei,imsi的处理(mtk,展讯,高通等) 目前国内对于双卡智能手机的需求还是很大的, ...

  5. android 短信数据库 双卡,关于android双卡手机sim卡信息采集适配的心得

    这几天通过对各个厂商的双卡信息适配的研究,总结了几点规律,写这篇心得主要是为了能够抛砖引玉,和大家一起分享,一起讨论,源码已上传. 一.android5.0以上(包含5.0)的版本双卡信息适配: 1. ...

  6. android 双卡开发获取sim卡默认数据卡,获取sim卡信息,sim1卡,sim2卡 2G/3G/4G信号强度

    1:默认数据卡 private int getDefalutDataID(){SubscriptionManager subscriptionManager = (SubscriptionManage ...

  7. android 判断有无sim卡,Android判断手机里是否有SIM卡

    由于项目的需要,要判断手机里是否有sim卡.在网上找了一下资料结果发现,网上的资料很多都是一样的,都是判断sim卡的状态,把代码添加进去后发现不能满足需求.然后就自己看了一下文档.代码如下. /** ...

  8. android 双卡手机发短信/判断手机是否为双卡

    本文转自:http://blog.csdn.net/xyz_lmn/article/details/7900439 try {Class<?> smsManagerClass = null ...

  9. 副卡显示无服务器,手机玩游戏时副卡无服务或收不到电话、短信怎么回事?

    适用产品: nova 6(全网通版 8gb+128gb),HUAWEI Mate RS 保时捷设计,HUAWEI Mate 40 RS 保时捷设计 典藏版,BEIDOU,HUAWEI Mate 30 ...

最新文章

  1. GIA张怡:关于小白入门AI算法工程师的直播分享
  2. Redis 限流的 3 种方式
  3. 赚票子、调身子、养孩子,陌陌的中年人生活有序展开
  4. vector 对某个下标排序_Python实现堆排序
  5. win10任务管理器快捷键_win10系统任务管理器怎么打开
  6. ISA2006无人值守安装
  7. react native bundle读取assets_react-native-easy-app 详解与使用之 (一)AsyncStorage
  8. TS Introduction(介绍)
  9. 交互设计[小插曲]--网站UI配色
  10. python代码怎么练_自己练习的Python代码(1)
  11. linux内存源码分析 - 伙伴系统(释放页框)
  12. Decorator设计模式(装饰)
  13. 省级面板数据(1990-2019):能源生产等(原油、石油、焦炭、原煤、天然气等)stata或excel版本
  14. 2021厦门LED照明产业展览会
  15. python爬股指期货数据_股指期货高频数据机器学习预测
  16. c语言怎么用右移代替除法,除法和算术右移之间的巧妙取代
  17. dns域名解析原理及过程
  18. 瑞幸咖啡2022,摆脱困境,迎来坦途
  19. Google mediapipe 人脸识别应用
  20. 【CV系列】昼夜图像区分算法

热门文章

  1. Redis连接开发工具---Jedis
  2. 【分享】高性能的PHP框架:Yii PHP Framework
  3. 新技术为视频直播助力
  4. 华为上半年手机销量_2019上半年手机销量排行榜 华为位居榜首
  5. 小马哥---高仿三星W2015主板型号F958机型 刷机拆机主板图
  6. html5新特性 gps,老生常谈H5新特性:地理定位
  7. VIP邮箱特权有哪些,TOMVIP邮箱可以注册靓号吗
  8. 从零开始学DedeCms模板,模板教程,从此模板制作不求人
  9. 博主:遇见未知的自己 (http://www.cnblogs.com)
  10. 【Ue4卡通渲染描边方案】平均法线存入切线的改进算法——O(n)时间复杂度