Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to monitor SIM state change

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 PhoneStateListener and reacts upon a LISTEN_SERVICE_STATE (when the state is OUT-OF-STATE it can get the SIM state from the TelephonyManager and look if the state is SIM_STATE_PIN_REQUIRED). So, my questions are:

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

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

like image 630
Gianni Costanzi Avatar asked May 10 '12 06:05

Gianni Costanzi


2 Answers

The Intent android.intent.action.SIM_STATE_CHANGED is 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:

  • Intent: android.intent.action.SIM_STATE_CHANGED with extras: ss = NOT_READY, reason = 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

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

like image 114
David Wasser Avatar answered Sep 23 '22 10:09

David Wasser


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.         }     } } 
like image 37
Tim Avatar answered Sep 21 '22 10:09

Tim