24

Mi piacerebbe essere in grado di fare qualcosa quando lo stato SIM cambia, cioè riprodurre un suono quando è richiesto il PIN SIM, ma penso che non ci siano eventi Broadcast che possono essere intercettati da un ricevitore broadcast per questo ... registrandosi per android.intent.action .PHONE_STATE ti dice solo quando cambia lo stato CALL. Un'alternativa può essere avviare un servizio che registra un PhoneStateListener e reagisce su un LISTEN_SERVICE_STATE (quando lo stato è OUT-OF-STATE può ottenere lo stato SIM dal TelephonyManager e controllare se lo stato è SIM_STATE_PIN_REQUIRED). Quindi, le mie domande sono:Come monitorare il cambio di stato SIM

1) C'è un intento trasmissione che posso usare per intercettare un cambiamento di stato SIM o di un cambiamento di servizio Stato?

2) è una cattiva idea di installare un PhoneStateListener all'interno di un Servizio e utilizzarlo per fornire intenti al servizio stesso momento della notifica di uno stato di telefono cambiato ricevuto dal PhoneStateListener?

risposta

23

L'intento android.intent.action.SIM_STATE_CHANGED viene trasmesso quando lo stato della SIM cambia. Per esempio, sul mio HTC Desire con una scheda di T-Mobile SIM, se ho messo il dispositivo in modalità di volo il seguente intento è trasmesso:

  • Intent: android.intent.action.SIM_STATE_CHANGED con gli extra: ss = NOT_READY , motivo = null

Se dunque io prendo dalla modalità di volo, le seguenti intenti vengono trasmessi:

  • Intent: android.intent.action.SIM_STATE_CHANGED con gli extra: ss = BLOCCATO, motivo = PIN
  • Scopi: android.intent.action.SIM_STATE_CHANGED con extra: ss = READY, motivo = null
  • intento: android.intent.action.SIM_STATE_CHANGED con extra: ss = IMSI, motivo = null
  • intento: android.intent .action.SIM_STATE_CHANGED con extra: ss = LOADED, motivo = null

È possibile che produttori diversi e modelli diversi si comportino in modo diverso. Come si suol dire, "Il tuo chilometraggio può variare".

+0

Grazie mille! Dove devo trovare queste informazioni all'interno dei documenti di riferimento Android? Sotto quale classe è documentato questo intento? –

+4

Non ho idea se o dove questo è documentato. L'ho scoperto empiricamente guardando il logcat per vedere quali Intenti vengono trasmessi quando si verificano determinati eventi telefonici e poi scrivendo piccoli programmi di test che ascoltano questi eventi e li scaricano. Dal momento che molti di questi sono specifici per i produttori, è praticamente necessario capirlo da soli. Felice di poter essere di aiuto. –

+0

Ho provato sul mio HTC One X e funziona, molte molte grazie! Non capisco perché alcune cose siano così scarsamente documentate nel riferimento ufficiale SDK (o forse la documentazione esiste ma è difficile da trovare) –

1

Il secondo approccio di avere un PhoneStateListener in un servizio che ascolta per onServiceStateChanged() ha funzionato per me. Credo che su alcuni dispositivi non si ottenga la trasmissione interna android.intent.action.SIM_STATE_CHANGED.

+0

"Credo che su alcuni dispositivi non si otterranno le broadcas interne" - Penso che si verifichi una funzionalità di sicurezza in cui la trasmissione non verrà consegnata se l'app non è ancora stata avviata dall'utente o la forza interrotta – for3st

2

La risposta di David è azzeccata. Volevo aggiungere un codice di esempio per aiutare le persone a iniziare a implementare un monitor di questo tipo.

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

funziona come un incantesimo! +1 –

Problemi correlati