在 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 的碎片化又缩小了一步