2015-10-26 10 views
12

Sono appena entrato nello sviluppo Android e ho deciso che la mia prima conquista in questo campo sarebbe stata capire come il telefono ha reagito alle chiamate in arrivo.Android, TelephonyManager, le gioie di PhoneStateListener e i numeri in entrata

Un po 'googling in seguito mi ha portato a http://www.compiletimeerror.com/2013/08/android-call-state-listener-example.html#.Vi3Ren4vfwM (quindi il mio codice condivide una sorprendente somiglianza con il suo/lei).

La mia principale attività (e solo) si presenta così:

import android.app.Activity; 
import android.content.Context; 
import android.os.Bundle; 
import android.telephony.PhoneStateListener; 
import android.telephony.TelephonyManager; 
import android.util.Log; 
import android.view.Menu; 
import android.widget.Toast; 

public class MainActivity extends Activity { 

@Override 
protected void onCreate(Bundle savedInstanceState) { 
    super.onCreate(savedInstanceState); 
    setContentView(R.layout.activity_main); 
    TelephonyManager TelephonyMgr = (TelephonyManager) getSystemService(Context.TELEPHONY_SERVICE); 
    TelephonyMgr.listen(new TeleListener(), 
      PhoneStateListener.LISTEN_CALL_STATE); 
} 
@Override 
public boolean onCreateOptionsMenu(Menu menu) { 
    getMenuInflater().inflate(R.menu.activity_main, menu); 
    return true; 
} 
class TeleListener extends PhoneStateListener { 
    public void onCallStateChanged(int state, String incomingNumber) { 
     super.onCallStateChanged(state, incomingNumber); 
     switch (state) { 
      case TelephonyManager.CALL_STATE_IDLE: 
       // CALL_STATE_IDLE; 
       Log.d("MyLittleDebugger", "I'm in " + state + " and the number is " + incomingNumber); 
       Toast.makeText(getApplicationContext(), "CALL_STATE_IDLE", 
         Toast.LENGTH_LONG).show(); 
       break; 
      case TelephonyManager.CALL_STATE_OFFHOOK: 
       // CALL_STATE_OFFHOOK; 
       Log.d("MyLittleDebugger", "I'm in " + state + " and the number is " + incomingNumber); 
       Toast.makeText(getApplicationContext(), "CALL_STATE_OFFHOOK", 
         Toast.LENGTH_LONG).show(); 
       break; 
      case TelephonyManager.CALL_STATE_RINGING: 
       // CALL_STATE_RINGING 
       Log.d("MyLittleDebugger", "I'm in " + state + " and the number is " + incomingNumber); 
       Toast.makeText(getApplicationContext(), incomingNumber, 
         Toast.LENGTH_LONG).show(); 
       Toast.makeText(getApplicationContext(), "CALL_STATE_RINGING", 
         Toast.LENGTH_LONG).show(); 
       break; 
      default: 
       break; 
     } 
    } 

} 
} 

Ora, ecco dove il divertimento si ferma. Ho fatto funzionare l'app su emulatore, e ho usato DDMS per falsificare alcune telefonate al mio dispositivo emulato per vedere dove sono caduti i pezzi.

E sicuramente abbastanza pane tostato spuntò e MyLittleDebugger divampato su swap di stato. L'ascoltatore stava funzionando, tuttavia nessun numero veniva mai mostrato nel mio registro o nel mio brindisi.

Era vuoto dove il numero avrebbe dovuto essere! Nulla o nulla, no, ma vuoto!

Dopo un po 'più googling, ho capito che il mio AndroidManifest.xml potrebbe essere il problema. E 'come segue:

<?xml version="1.0" encoding="utf-8"?> 
<manifest xmlns:android="http://schemas.android.com/apk/res/android" 
package="com.example.x.xy" > 

<uses-permission android:name="android.permission.READ_PHONE_STATE" /> 

<application 
    android:allowBackup="true" 
    android:icon="@mipmap/ic_launcher" 
    android:label="@string/app_name" 
    android:supportsRtl="true" 
    android:theme="@style/AppTheme" > 
    <activity android:name=".MainActivity" > 
     <intent-filter> 
      <action android:name="android.intent.action.MAIN" /> 

      <category android:name="android.intent.category.LAUNCHER" /> 
     </intent-filter> 
    </activity> 
</application> 

Ora, ecco la domanda: che cosa mi manca?

Chiaramente, una piccola parte di qualcosa è andata male da qualche parte, perché sono in grado di avere l'oggetto .listen() per chiamare gli stati, ma non riesco a ottenere il numero da mostrare.

Nuove informazioni:

Ho anche provato questo sul mio telefono, non emulando al esattamente lo stesso risultato.

+0

Ho eseguito il codice e ha funzionato per me. # è apparso usando la chiamata simulata con ddm. – JJF

+0

Anche la mia app non funzionerebbe nemmeno se non avessi dato il permesso READ_PHONE_STATE. Sembra diverso da quello che hai visto. Su quali versioni di Android hai provato questo? – JJF

+0

Ho lo stesso identico problema ma il ricevitore non funziona per me. – Mainak

risposta

4

Probabilmente è necessario utilizzare il ricevitore di trasmissione che può essere d'aiuto per ciò che si sta cercando di ottenere. crea una classe che estende il destinatario della trasmissione e tenta di catturare il numero in entrata.

public class MyReceiver extends BroadcastReceiver { 

    @Override 
    public void onReceive(final Context context, Intent intent) { 
     TelephonyManager mtelephony = (TelephonyManager)context.getSystemService(Context.TELEPHONY_SERVICE); 
     mtelephony.listen(new PhoneStateListener(){ 
      @Override 
      public void onCallStateChanged(int state, String incomingNumber) { 
       super.onCallStateChanged(state, incomingNumber); 
       switch (state) { 
       case TelephonyManager.CALL_STATE_RINGING: 
       // CALL_STATE_RINGING 
       Log.d("MyLittleDebugger", "I'm in " + state + " and the number is " + incomingNumber); 
      Toast.makeText(getApplicationContext(), incomingNumber, 
        Toast.LENGTH_LONG).show(); 
      Toast.makeText(getApplicationContext(), "CALL_STATE_RINGING", 
        Toast.LENGTH_LONG).show(); 
      break; 
     default: 
      break; 
       } 
      } 
     },PhoneStateListener.LISTEN_CALL_STATE); 
    } 

e nel file manifest anche questa riga.

 <receiver android:name=".MyReceiver" > 
      <intent-filter> 
       <action android:name="android.intent.action.PHONE_STATE" /> 
      </intent-filter> 
     </receiver> 
+1

Risposta molto bella! +1 e la taglia va a te! Grazie! – ViRALiC

+0

Anche in questo caso, il mio problema non viene risolto. A volte il numero in entrata è ancora vuoto. – Naved

3

Ti consiglierei di eseguire la tua app su un vero telefono funzionante!

Ci sono diversi motivi per cui un numero di telefono non è disponibile su tutte le notifiche, ma si ha una migliore possibilità che ce ne sia uno se la chiamata proviene da una rete telefonica reale che può fornire il numero.

+0

L'ho provato, dopo aver originariamente pubblicato la domanda. Non è l'errore. Ti darò un +1 per il buon suggerimento, e potrebbe essere stato l'errore, ma non è stato in questo caso. – ViRALiC

2

Non ho usato la funzione di listenTelephonyManager, ma ho usato con successo un BroadcastReceiver per ottenere i cambiamenti di stato del telefono e il numero di telefono.

Pubblica il tuo ricevitore in attività o nel Manifesto (se si desidera ricevere aggiornamenti quando l'applicazione è in background):

attività:

@Override 
protected void onResume() { 
    super.onResume(); 
    BroadcastReceiver receiver = new PhoneStateBroadcastReceiver(); 
    IntentFilter filter= new IntentFilter(); 
    filter.addAction("android.intent.action.PHONE_STATE"); 
    filter.addAction("android.intent.action.NEW_OUTGOING_CALL"); 
    registerReceiver(reciever, filter); 
} 

@Override 
protected void onPause() { 
    super.onPause(); 
    unregisterReceiver(reciever); 
} 

manifesto:

<receiver 
    android:name=".PhoneStateBroadcastReceiver" 
    android:permission="android.permission.READ_PHONE_STATE" > 
    <intent-filter> 
     <action android:name="android.intent.action.PHONE_STATE" /> 
     <action android:name="android.intent.action.NEW_OUTGOING_CALL" /> 
    </intent-filter> 
</receiver> 

e un ricevitore base:

public class PhoneStateBroadcastReceiver extends BroadcastReceiver { 
    private final String TAG = getClass().getName(); 
    private static String number = null; 

    @Override 
    public void onReceive(final Context context, final Intent intent) { 
     if (intent.getAction().equals(TelephonyManager.ACTION_PHONE_STATE_CHANGED)) { 
     String state = intent.getStringExtra(TelephonyManager.EXTRA_STATE); 
     Log.d(TAG, intent.getAction() + ", EXTRA_STATE: " + state); 
     // on ringing get incoming number 
     if (state.equals(TelephonyManager.EXTRA_STATE_RINGING)) { 
      number = intent.getStringExtra(TelephonyManager.EXTRA_INCOMING_NUMBER); 
      Log.d(TAG, "EXTRA_INCOMING_NUMBER: " + number); 

     } 
     } 

     if (intent.getAction().equals(Intent.ACTION_NEW_OUTGOING_CALL)) { 
     number = intent.getStringExtra(Intent.EXTRA_PHONE_NUMBER); 
     Log.d(TAG, intent.getAction() + ", EXTRA_PHONE_NUMBER: " + number); 
     } 

    } 

} 

e in questa risposta SO è possibile trovare una buona implementazione che gestisce anche più chiamate: https://stackoverflow.com/a/15564021/348378

+1

Grazie, questa è stata una buona spiegazione, ma ho capito che funzionava con la risposta di danwcode. +1! – ViRALiC

+1

Prego, lui ha risposto prima di me ma ho sentito che un po 'di più è necessario. Dovresti notare che PHONE_STATE da solo non ti dà il numero delle chiamate in uscita, per cui è necessario registrare anche NEW_OUTGOING_CALL. Inoltre, la soluzione manifest renderà la tua applicazione ricevere eventi anche quando la tua app non è in primo piano. – Raanan