28

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

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

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

4

3 回答 3

33

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

  • 意图:android.intent.action.SIM_STATE_CHANGED 附加:ss = NOT_READY,reason = null

如果我随后将其退出飞行模式,则会广播以下 Intent:

  • 意图:android.intent.action.SIM_STATE_CHANGED 附加:ss = LOCKED,reason = PIN
  • 意图:android.intent.action.SIM_STATE_CHANGED 附加:ss = READY,reason = null
  • 意图:android.intent.action.SIM_STATE_CHANGED 附加:ss = IMSI,原因 = null
  • 意图:android.intent.action.SIM_STATE_CHANGED 附加:ss = LOADED,reason = null

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

于 2012-05-11T14:36:55.000 回答
5

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

/**
 * 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.
        }
    }
}
于 2017-04-24T13:00:46.437 回答
2

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

于 2014-01-16T16:51:53.560 回答