原文地址:http://m.blog.csdn.net/article/details?id=50039589
最近由于一个sim卡相关的需求,就去了解了一下Android Sim卡相关的一些代码.在此记录一下.
简要说一下需求吧,需要在插拔卡的时候弹出对话框,提供界面让用户选择开启默认卡数据链接或者转移到另一张卡开启数据链接.这个主要就是监听sim卡的状态.sim卡的状态.一般网上搜到的都是广播--"android.intent.action.SIM_STATE_CHANGED"
- public void onReceive(Context context, Intent intent) {
- System.out.println("sim state changed");
- if (intent.getAction().equals(ACTION_SIM_STATE_CHANGED)) {
- TelephonyManager tm = (TelephonyManager)context.getSystemService(Service.TELEPHONY_SERVICE);
- int state = tm.getSimState();
- switch (state) {
- case TelephonyManager.SIM_STATE_READY :
- simState = SIM_VALID;
- break;
- case TelephonyManager.SIM_STATE_UNKNOWN :
- case TelephonyManager.SIM_STATE_ABSENT :
- case TelephonyManager.SIM_STATE_PIN_REQUIRED :
- case TelephonyManager.SIM_STATE_PUK_REQUIRED :
- case TelephonyManager.SIM_STATE_NETWORK_LOCKED :
- default:
- simState = SIM_INVALID;
- break;
- }
- }
- }
上面的代码是引用网上的一段,接受到SIM_STATE_CHANGED广播后,调用TelephoneManager 的getsinstate()函数获取广播的参数,上面的一些有些旧了,我参考了一下安卓
5.1的源码:
- * These are the ordinal value of IccCardConstants.State.
- */
- public static final int SIM_STATE_UNKNOWN = 0;
- /** SIM card state: no SIM card is available in the device */
- public static final int SIM_STATE_ABSENT = 1;
- /** SIM card state: Locked: requires the user's SIM PIN to unlock */
- public static final int SIM_STATE_PIN_REQUIRED = 2;
- /** SIM card state: Locked: requires the user's SIM PUK to unlock */
- public static final int SIM_STATE_PUK_REQUIRED = 3;
- /** SIM card state: Locked: requires a network PIN to unlock */
- public static final int SIM_STATE_NETWORK_LOCKED = 4;
- /** SIM card state: Ready */
- public static final int SIM_STATE_READY = 5;
- /** SIM card state: SIM Card is NOT READY
- *@hide
- */
- public static final int SIM_STATE_NOT_READY = 6;
- /** SIM card state: SIM Card Error, permanently disabled
- *@hide
- */
- public static final int SIM_STATE_PERM_DISABLED = 7;
- /** SIM card state: SIM Card Error, present but faulty
- *@hide
- */
- public static final int SIM_STATE_CARD_IO_ERROR = 8;
一共9种状态,每种都有解释,但是可以发现其中有代表没插卡的SIM_STATE_ABSENT,代表卡正常的SIM_STATE_READY,但是没有代表插入卡的广播.不符合我的需求啊.无奈继续找.
而我这里需要监听插卡弹出提示框,所以我查看了framework相关源码.一般和通讯相关源码都在frameworks/opt/telephony/,frameworks/base/telephony/,frameworks/base/telecom/这三个模块下.
但是我发现sim卡相关的很多都在frameworks/opt/telephony/这个目录下.
由于之前做过数据连接相关的工作,而数据链接又和sim卡挂钩,所以我直接找到了frameworks/opt/telephony/src/java/com/mediatek/internal/telephony/dataconnection/DataSubSelector.java这个文件.
这个文件是控制插卡,设置默认卡为卡一或者卡二,同时也控制数据连接的开关.这部分功能和我的需求还是很类似的.
进入这个文件可以发现他就是一个接收广播的文件,而接收的广播就是TelephonyIntents.ACTION_SUBINFO_RECORD_UPDATED.
查看这个广播
- public static final String ACTION_SUBINFO_RECORD_UPDATED
- = "android.intent.action.ACTION_SUBINFO_RECORD_UPDATED";
源码中对他的解释就是:It indicates subinfo record update is completed when SIM inserted state change.
可以发现这才是监听sim卡插入的广播.找到这个广播,于是可以做起来了.
补充:后来我又深入的查看一些文件,发现frameworks/opt/telephony/src/java/com/android/internal/telephony/SubscriptionInfoUpdater.java文件,从文件名就可以知道这是sim卡信息更新的文件.
既然sim卡信息更新,那肯定和插卡,拔卡有关.果然在这个文件我发现了一个数组:
- /**
- * int[] sInsertSimState maintains all slots' SIM inserted status currently,
- * it may contain 4 kinds of values:
- * SIM_NOT_INSERT : no SIM inserted in slot i now
- * SIM_CHANGED : a valid SIM insert in slot i and is different SIM from last time
- * it will later become SIM_NEW or SIM_REPOSITION during update procedure
- * SIM_NOT_CHANGE : a valid SIM insert in slot i and is the same SIM as last time
- * SIM_NEW : a valid SIM insert in slot i and is a new SIM
- * SIM_REPOSITION : a valid SIM insert in slot i and is inserted in different slot last time
- * positive integer #: index to distinguish SIM cards with the same IccId
- */
这个数组详细的介绍了插卡的sim卡状态的变化.
于是把原来的代码优化,放弃之前的广播,在这个文件中只有sInsertSimState = SIM_NEW,才触发我的代码发出自己的广播来弹出提示框(这里这样修改是为了防止每次插重复的卡都要弹出框,因为android自动会把之前的卡的状态,数据的开关写入系统的SettingProvider之中记录下来 .).所以只有新卡插入才会提示用户设置.