这里仅以获取sim卡的IMSI接口(getSubscriberId)和发短信接口(sendTextMessage)为例来详细讲解一下Android5.0-6.0双卡适配的策略,其他方面的双卡适配方案跟4.4以前相比并无特别大的区别,之前我们已有专家对此进行过详细的总结,这里就不重复说明了。
所有插入过的SIM卡的相关信息都会存储在这个表里,再看看表里的字段,这里截图只截了前面的几个比较关键的字段
_id是表的主键,代表sim卡数据的索引值,从1开始,每次新插入的一张sim卡,数据表都会插入一行新数据,该行数据的_id值每次递增1(1,2,3,4,5……n这样递增),而不是更换一张卡更新一下对应卡槽的数据行的sim卡数据。
sim_id代表当前卡所在的卡槽值,只有0,1,-1三个值,0代表当前卡插在卡槽1当中(主卡槽),1代表当前卡插在卡槽2当中(副卡槽),-1代表曾经手机插入过此卡,现在已经移除。
其次从加入的API来看,Google加入了一系列管理双卡信息的类,其主要框架如下图所示:
而SubscriptionManager这个类提供了一个关键的方法给上层开发来查询使用,这里只对它的这个关键方法进行一下简单分析。
方法名是:getSubId,获取指定卡槽sim卡的subId,对应的就是前面所讲的数据表中的_id值。为什么说这个方法对上层开发来说非常关键,咱们先来看一下5.0-6.0的前面提到的要适配的两个接口是怎么设计的,大家就知道它为什么关键了,在这里先卖个关子。
Android5.0开始,不单加入了上面这些一系列管理双卡信息的API,也加入了获取各sim卡信息状态以及调用不同sim卡发短信的接口。
大家都知道平时咱们开发的发短信功能大多数是调用SmsManager类提供的sendTextMessage方法来发短信的,但是对于双卡手机来讲,按照之前常规的方式,只能是通过默认卡发出短信,那该怎么办呢?先来看一段代码截图:
这段代码的截图是SDK5.1中的SmsManager代码片段,英文注释就不详细翻译了,相信英文大神无处不在,我就不献丑了,大家自己翻译一下就好。
大家看到了什么?没错:
@param subId an SMS subscription id, typically accessed using
@return the instance of the SmsManager associated with subId
这两行关键注释,进一步提炼一下,subId,subId,subId啊啊啊,关键词重复三遍。
到这里大家是不是豁然开朗,一目了然前面所卖的关子的原因:通过subId可以获取到对应sim卡的SmsManager实例,而subId正是通过SubscriptionManager的getSubId方法来获取的,有了对应sim卡的SmsManager实例之后,按照以前的方法通过调用该实例的sendTextMessage方法就可以实现通过不同卡发短信的需求了。
下面再说一下获取IMSI的适配方案:
理解了发短信的方案之后,下面这个方案也很好理解,直接看代码:
也是在TelephonyManager类里面新增了一个带参数的getSubscriberId方法,大家应该早已发现,参数也是subId,没错就是它。再一次证明了SubscriptionManager的getSubId方法的关键性。
适配方案就是通过phone服务获取TelephonyManager的实例,从而调用这个带参数的getSubscriberId方法来获取对应sim卡的IMSI,OK搞定。
说到这里,既然getSubId方法这么关键,咱们再返回来一睹SubscriptionManager的getSubId方法代码的风采:
讲到这里,方案看上去貌似挺完美,但是真的是这样吗?甚至细心的朋友会怀疑:你这只是官方新增的标准API,称不上适配吧?
没错,事情并没有这么简单,这些只能算是5.0以后实现双卡需求的一个标准解决方案,只能应对极其少数几个有节操的大厂的ROM还可以,比如三星,做到现在发现5.0以后的三星ROM都很规矩(题外话)。
标准!标准!标准!有节操!有节操!有节操的大厂,那么针对那些大多数没节操的厂商该怎么办?
别急,方案还是有的,做到目前为止,发现会出现适配性问题的地方都是发生在SubscriptionManager和SmsManager身上,比如有的ROM没有了SubscriptionManager类,有的改名了,有点改方法名了等等。
那么怎么应对subId这个问题?
仔细想想,前面我说过subId就是数据表中_id的值,其实SubscriptionManager底层的实现也是通过查询这个表得到的。那么我们就管你改成什么了,果断通过传入卡槽值(sim_id)来查询sim卡的_id值不就OK了么。事实也证明此方案可行,具体代码如下:
通过这个方法来获取到subId值来提供给发短信和获取IMSI接口使用,完美解决了以上存在是适配性问题。
然而SmsManager如果也被修改了怎么办,继续看一下下面的代码截图:
最后补充一点,前面所用示例代码都是通过Android5.1获取的,其中5.0-6.0不同版本是有区别的:
1、getSubscriberId各版本的区别: