2015-10-26 4 views
12

Ich habe sehr neu in Android Entwicklung bekommen, und entschied, dass meine erste Eroberung auf diesem neuen Gebiet wäre zu erfassen, wie das Telefon auf eingehende Anrufe reagiert.Android, TelephonyManager, die Freuden von PhoneStateListener und eingehende Nummern

Ein wenig googeln führte mich später zu http://www.compiletimeerror.com/2013/08/android-call-state-listener-example.html#.Vi3Ren4vfwM (so hat mein Code eine frappierende Ähnlichkeit zu seinem/ihr).

Mein Haupt (und einzige) Aktivität sieht wie folgt aus:

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; 
     } 
    } 

} 
} 

Nun, hier ist, wo der Spaß aufhört. Ich habe die App auf Emulator laufen lassen und DDMS verwendet, um ein paar Telefonanrufe auf mein emuliertes Gerät zu spoofen, um zu sehen, wo die Stücke gelandet sind.

Und sicherlich genug Toast aufgetaucht und MyLittleDebugger flammte bei staatlichen Swaps. Der Zuhörer arbeitete, aber in meinem Logbuch oder meinem Toast wurde nie eine Nummer angezeigt.

Es war nur leer, wo die Nummer hätte sein sollen! Nicht null oder irgendetwas, nein, aber leer!

Nach ein wenig mehr googeln, erkannte ich, dass meine AndroidManifest.xml könnte das Problem sein. Es ist wie folgt:

<?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> 

Nun, hier ist die Frage: Was bin ich dabei?

Offensichtlich ist ein kleiner Bruchteil von etwas irgendwo falsch gelaufen, weil ich mein TelephonyMgr Objekt .listen() haben kann, um Zustände zu nennen, aber ich kann die Zahl nicht bekommen, um zu zeigen.

Neue Informationen:

Ich habe dies auch versucht, auf meinem Handy, ohne auf das exakt gleiche Ergebnis zu emulieren.

+0

Ich lief Ihren Code und es hat für mich funktioniert. # tauchte mit ddm gefälschten Anruf auf. – JJF

+0

Auch meine App würde nicht einmal ausgeführt, wenn ich es nicht READ_PHONE_STATE Erlaubnis geben würde. Das klingt anders als das, was du gesehen hast. Mit welchen Versionen von Android hast du das versucht? – JJF

+0

Ich habe genau das gleiche Problem, aber der Rundfunkempfänger funktioniert nicht für mich. – Mainak

Antwort

4

Sie müssen wahrscheinlich Broadcast-Empfänger verwenden, die Ihnen helfen können, was Sie erreichen möchten. erstellen Klasse erweitern Broadcast-Empfänger und in dem versuchen, die eingehende Nummer zu fangen.

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); 
    } 

und in Ihrem Manifest auch diese Zeile.

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

Sehr nette Antwort! +1 und das Kopfgeld geht an dich! Vielen Dank! – ViRALiC

+0

Dadurch wird auch mein Problem nicht gelöst. Es ist immer noch manchmal die eingehende Nummer leer. – Naved

3

Ich würde Ihnen empfehlen, Ihre App auf einem echten funktionierenden Telefon zu betreiben!

Es gibt mehrere Gründe, warum eine Telefonnummer nicht für alle Benachrichtigungen verfügbar ist. Sie haben jedoch eine wesentlich höhere Wahrscheinlichkeit, dass eine solche Nummer vorhanden ist, wenn der Anruf von einem echten Telefonnetz stammt, das die Nummer bereitstellen kann.

+0

Ich habe das versucht, nachdem ich die Frage ursprünglich gestellt hatte. Es ist nicht der Fehler. Ich gebe Ihnen einen +1 für den guten Vorschlag, und es könnte der Fehler gewesen sein, aber es war nicht in diesem Fall. – ViRALiC

2

habe ich die listen Funktion von TelephonyManager nicht verwendet, aber ich BroadcastReceiver erfolgreich nutzte die Telefonzustandsänderungen für das Abrufen und die Telefonnummer.

Ihr Empfänger im Aktivitäts Registrieren oder im Manifest (wenn Sie Updates erhalten möchten, wenn die App im Hintergrund ist):

Aktivität:

@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); 
} 

Manifest:

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

und ein Basisempfänger:

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); 
     } 

    } 

} 

und in dieser SO-Antwort finden Sie eine nette Implementierung, die auch mehrere Anrufe behandelt: https://stackoverflow.com/a/15564021/348378

+1

Danke, das war eine gute Erklärung, aber ich habe es mit der Antwort von Danwcode arbeiten lassen. +1! – ViRALiC

+1

Gern geschehen, er hat vor mir geantwortet, aber ich habe ein bisschen mehr gebraucht. Sie sollten bemerken, dass PHONE_STATE alleine nicht die Nummer für ausgehende Anrufe angibt, für die Sie auch den NEW_OUTGOING_CALL registrieren müssen. Zusätzlich wird die Manifest-Lösung dazu führen, dass Ihre Anwendung auch dann ein Ereignis erhält, wenn sich Ihre App nicht im Vordergrund befindet. – Raanan