24

Chciałbym móc zrobić kilka rzeczy po zmianie stanu karty SIM, np. Odtwarzać dźwięk, gdy wymagany jest PIN karty SIM, ale myślę, że nie ma zdarzeń rozgłoszeniowych, które mogą zostać przechwycone przez odbiornik dla tego ... rejestracja dla android.intent.action .PHONE_STATE informuje tylko o zmianie stanu WYWOŁANIA. Alternatywą może być uruchomienie usługi rejestrowania numeru PhoneStateListener i reaguje na LISTEN_SERVICE_STATE (kiedy Stan jest OUT-OF-STATE może uzyskać stan SIM z TelefoniaManager i sprawdzić, czy stan SIM_STATE_PIN_REQUIRED). Moje pytania to:Jak monitorować zmianę stanu karty SIM

1) Czy istnieje zamiar transmisji, który mogę wykorzystać do przechwycenia zmiany stanu karty SIM lub zmiany stanu usługi?

2) jest to zły pomysł, aby zainstalować PhoneStateListener w usłudze i użyć go do dostarczenia intencji do samego doręczenia zawiadomienia o stanie telefonu zmienił otrzymane przez PhoneStateListener?

Odpowiedz

23

Intent android.intent.action.SIM_STATE_CHANGED jest nadawany, gdy zmienia się stan karty SIM. Na przykład, na moim HTC Desire z kartą SIM T-Mobile, jeśli mogę umieścić urządzenie w tryb lotu następujące Intent jest nadawany:

  • zamiar: android.intent.action.SIM_STATE_CHANGED z dodatkami: SS = NOT_READY , powód = null

Gdybym następnie wyjąć ją z trybu lotu, następujące metody są nadawane:

  • zamiar: android.intent.action.SIM_STATE_CHANGED z dodatkami: ss = zablokowane, powodem = PIN
  • zamiar: android.intent.action.SIM_STATE_CHANGED z dodatkami: ss = gotowy powód = null
  • zamiar: android.intent.action.SIM_STATE_CHANGED z dodatkami: ss = IMSI, powód = null
  • zamiar: android.intent .action.SIM_STATE_CHANGED z dodatkami: ss = LOADED, reason = null

Jest możliwe, że różni producenci i różne modele zachowują się inaczej. Jak mówią: "Twój przebieg może się różnić".

+0

Wielkie dzięki! Gdzie powinienem znaleźć te informacje w Dokumentach referencyjnych systemu Android? W jakiej klasie jest to udokumentowane? –

+4

Nie mam pojęcia, czy i gdzie jest to udokumentowane. Odkryłem to empirycznie, obserwując logcat, aby zobaczyć, jakie intencje są transmitowane, gdy występują pewne zdarzenia telefoniczne, a następnie piszą małe programy testowe, które nasłuchują tych zdarzeń i zrzucają ich zawartość. Ponieważ wiele z tego jest specyficzne dla dostawcy, musisz go sam sobie wymyślić. Cieszę się, że mogę ci pomóc. –

+0

Testowałem na moim HTC One X i działa, wiele dzięki! Nie rozumiem, dlaczego niektóre rzeczy są tak słabo udokumentowane w oficjalnym referencji SDK (a może dokumentacja istnieje, ale trudno ją znaleźć) –

1

Drugie podejście polegające na posiadaniu PhoneStateListener w usłudze, która nasłuchuje dla onServiceStateChanged(), było dla mnie przydatne. Wierzę, że na niektórych urządzeniach nie otrzymasz transmisji wewnętrznej android.intent.action.SIM_STATE_CHANGED.

+0

"Wierzę, że na niektórych urządzeniach nie uzyskasz dostępu do sieci wewnętrznej" - myślę, że natrafisz na funkcję bezpieczeństwa, w której transmisja nie zostanie dostarczona, jeśli aplikacja nie została jeszcze uruchomiona przez użytkownika lub zatrzymana siła – for3st

2

Odpowiedź Dawida jest natychmiastowa. Chciałem dodać przykładowy kod, aby pomóc ludziom rozpocząć wdrażanie takiego monitora stanu.

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

działa jak urok! +1 –

Powiązane problemy