Android 如何监控 SIM 卡状态变化

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/10528464/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-20 04:02:33  来源:igfitidea点击:

How to monitor SIM state change

androidbroadcastreceiverandroid-servicetelephonymanager

提问by Gianni Costanzi

I'd like to be able to do some stuff when the SIM state change, i.e. play a sound when SIM PIN is required, but I think there are no Broadcast events that can be intercepted by a broadcast receiver for this... registering for android.intent.action.PHONE_STATE does only tell you when the CALL-STATE changes.. An alternative can be starting a service that registers a PhoneStateListenerand reacts upon a LISTEN_SERVICE_STATE (when the state is OUT-OF-STATE it can get the SIM state from the TelephonyManagerand look if the state is SIM_STATE_PIN_REQUIRED). So, my questions are:

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

1)Is there any broadcast intent that I can use to intercept a SIM state change or a Service State change?

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

2)is it a bad idea to install a PhoneStateListenerwithin a Service and use it to deliver intents to the Service itself upon the notification of a phone state changed received by the PhoneStateListener?

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

回答by David Wasser

The Intent android.intent.action.SIM_STATE_CHANGEDis broadcast when the SIM state changes. For example, on my HTC Desire with a T-Mobile SIM card, if I put the device into flight mode the following Intent is broadcast:

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

  • Intent: android.intent.action.SIM_STATE_CHANGED with extras: ss = NOT_READY, reason = null
  • 意图:android.intent.action.SIM_STATE_CHANGED 与附加:ss = NOT_READY,原因 = null

If I then take it out of flight mode, the following Intents are broadcast:

如果我将其退出飞行模式,则会广播以下意图:

  • 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
  • 意图: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

It is possible that different manufacturers and different models behave differently. As they say, "Your mileage may vary".

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

回答by Tim

David's answer is spot on. I wanted to add some example code to help people get started with implementing such a state monitor.

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

/**
 * 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.
        }
    }
}

回答by VladimirVip

The second approach of having a PhoneStateListenerin a Service that listens for onServiceStateChanged()worked for me. I believe that on some devices you will not get the internal broadcast android.intent.action.SIM_STATE_CHANGED.

具有的第二种方法PhoneStateListener的服务,对于监听onServiceStateChanged()为我工作。我相信在某些设备上您将无法获得内部广播android.intent.action.SIM_STATE_CHANGED