在 Android 5.0 以前,各芯片厂商上的双卡开发没有一个统一的标准,以至于做起双卡适配来十分麻烦。 Android 5.0 之后,Google 官方统一了双卡平台的适配,并在 Framework 中添加了双卡相关的 API,这对于需要处理双卡的应用来说提供了很大的便利。
因为 Android 5 上的双卡 API 还不是很完善 所以本文是介绍在 Android 6.0 平台上的双卡相关开发 后续还会有一篇文章来介绍在双卡处理 Android N 上的实现
 
言归正题 在 API 层面上,自 Android 5.0 开始,加入了 SubscriptionManager。双卡相关的处理主要是依赖这个 API,你可以通过 Context 类里面的 getSystemService 方法和 SubscriptionManager.from(Context) 来取得它的对象,当然它内部也是调用的 getSystemService。
在数据库方面,TelephonyProvider 的 telephony.db 中新增了 siminfo 表来管理双卡的信息
由于字段太多,我这里只截图了几个关键的字段 需要注意的是 _id  和 sim_id  这两个字段 _id: 这个不用多说,系统要求,自增长,从 0 开始 sim_id:该行的卡所在的卡槽值,有 0,1,-1 三个值 | 数值 | 描述                        | | :–: |:—————————:| | 0    | 该卡插在卡槽 1 中(主卡槽) | | 1    | 该卡插在卡槽 2 中(副卡槽) | | -1   | 手机内曾经插入过该卡        |Ps. 在 Android 6.0+,-1 值已经被移除 
每插入一张新的 SIM 卡,siminfo 表中就会插入一行新的数据,然后 _id 会自增长加 1
详细的各个 API 可以去查阅 API 文档。我这里仅以获取双卡手机两个卡的 IMSI 为例,介绍一下各平台所使用的方法 SubId 这个值对于双卡相关的操作来说是必要的
Android 6.0:
1 2 3 4 5 6 7 8 9 10 11 TelePhonyManager.getPhoneCount() SubscriptionManager subManager = SubscriptionManager.from(this ); SubscriptionInfo info = subManager.getActiveSubscriptionInfoForSimSlotIndex(1 ); int  subId = info.getSubscriptionId();TelephonyManager teleManager = getSystemService(TelephonyManager.class); String imsi = teleManager.getSubscriberId(subId); 
 
MTK:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 try  {    TelephonyManager teleManager = getSystemService(TelephonyManager.class);     Class<?> phoneClass = Class.forName("com.android.internal.telephony.Phone" );     Field gemni1Field = phoneClass.getField("GEMINI_SIM_1" );     Field gemni2Field = phoneClass.getField("GEMINI_SIM_2" );     gemni1Field.setAccessible(true );     gemni2Field.setAccessible(true );     int  simId1 = (int ) gemni1Field.get(null );     int  simId2 = (int ) gemni2Field.get(null );     Method method = TelephonyManager.class.getDeclaredMethod("getSubscriberIdGemini" , int .class);     String imsi1 = (String) method.invoke(teleManager, simId1);     String imsi2 = (String) method.invoke(teleManager, simId2); } catch  (Exception e) {     e.printStackTrace(); } 
 
高通:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 try  {    Class<?> msmTeleManager = Class.forName("android.telephony.MSimTelephonyManager" );     Method method = msmTeleManager.getMethod("getSubscriberId" , int .class);     int  simId1 = 0 ;     int  simId2 = 1 ;     Object phoneMsim = getSystemService("phone_msim" );     String imsi1 = (String) method.invoke(phoneMsim, simId1);     String imsi2 = (String) method.invoke(phoneMsim, simId2); } catch  (Exception e) {     e.printStackTrace(); } 
 
对比三种获取双卡 IMSI 的方式,可以看出 Android 原生支持的双卡 API 更加的规范标准。目前新出的 Android 5+ 的新机上基本都采用了原生 API,Android 的碎片化又缩小了一步