如何监控SIM状态变化

时间:2012-05-10 06:19:29

标签: android broadcastreceiver android-service telephonymanager

我希望能够在SIM状态改变时做一些事情,即在需要SIM PIN时播放声音,但我认为没有广播事件可以被广播接收器截获。注册 android.intent.action .PHONE_STATE只会告诉你CALL-STATE何时发生变化。另一种方法是启动一个注册 PhoneStateListener 的服务并作出反应LISTEN_SERVICE_STATE(当状态为OUT-STATE时,它可以从 TelephonyManager 获取SIM状态,并查看状态是否为SIM_STATE_PIN_REQUIRED)。所以,我的问题是:

1)是否有任何广播意图可用于拦截SIM状态更改或服务状态更改?

2)在服务中安装 PhoneStateListener 是一个坏主意,并在收到电话状态更改通知后使用它向服务本身传递意图通过 PhoneStateListener

3 个答案:

答案 0 :(得分:28)

当SIM状态发生变化时,会广播Intent android.intent.action.SIM_STATE_CHANGED。例如,在我的带有T-Mobile SIM卡的HTC Desire上,如果我将设备置于飞行模式,则广播以下意图:

  • Intent:android.intent.action.SIM_STATE_CHANGED with extras:ss = NOT_READY,reason = null

如果我将其从飞行模式中取出,则广播以下意图:

  • Intent:android.intent.action.SIM_STATE_CHANGED with extras:ss = LOCKED,reason = PIN
  • Intent:android.intent.action.SIM_STATE_CHANGED with extras:ss = READY,reason = null
  • Intent:android.intent.action.SIM_STATE_CHANGED with extras:ss = IMSI,reason = null
  • Intent:android.intent.action.SIM_STATE_CHANGED with extras:ss = LOADED,reason = null

不同制造商和不同型号可能表现不同。正如他们所说,“你的里程可能会有所不同”。

答案 1 :(得分:3)

大卫的回答很明显。我想添加一些示例代码,以帮助人们开始实现这样的状态监视器。

/**
 * Handles broadcasts related to SIM card state changes.
 * <p>
 * Possible states that are received here are:
 * <p>
 * Documented:
 * ABSENT
 * NETWORK_LOCKED
 * PIN_REQUIRED
 * PUK_REQUIRED
 * READY
 * UNKNOWN
 * <p>
 * Undocumented:
 * NOT_READY (ICC interface is not ready, e.g. radio is off or powering on)
 * CARD_IO_ERROR (three consecutive times there was a SIM IO error)
 * IMSI (ICC IMSI is ready in property)
 * LOADED (all ICC records, including IMSI, are loaded)
 * <p>
 * Note: some of these are not documented in
 * https://developer.android.com/reference/android/telephony/TelephonyManager.html
 * but they can be found deeper in the source code, namely in com.android.internal.telephony.IccCardConstants.
 */
public class SimStateChangedReceiver extends BroadcastReceiver {

    /**
     * This refers to com.android.internal.telehpony.IccCardConstants.INTENT_KEY_ICC_STATE.
     * It seems not possible to refer it through a builtin class like TelephonyManager, so we
     * define it here manually.
     */
    private static final String EXTRA_SIM_STATE = "ss";

    @Override
    public void onReceive(Context context, Intent intent) {

        String state = intent.getExtras().getString(EXTRA_SIM_STATE);
        if (state == null) {
            return;
        }

        // Do stuff depending on state   
        switch (state) {      
            case "ABSENT": break;
            case "NETWORK_LOCKED": break;
            // etc.
        }
    }
}

答案 2 :(得分:1)

在侦听PhoneStateListener的服务中使用onServiceStateChanged()的第二种方法为我工作。我相信在某些设备上你不会得到内部广播android.intent.action.SIM_STATE_CHANGED