Wie erkenne ich eingehende Anrufe auf einem Android-Gerät?

130

Ich versuche eine App wie zu erstellen, wenn ein Anruf an das Telefon kommt, möchte ich die Nummer erkennen. Im Folgenden habe ich versucht, aber eingehende Anrufe werden nicht erkannt.

Ich möchte meinen MainActivityHintergrund ausführen . Wie kann ich das tun?

Ich hatte die Erlaubnis in der manifestAkte gegeben.

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

Gibt es noch etwas, das ich im Manifest angeben sollte?

public class MainActivity extends Activity {
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.test_layout);
   }

   public class myPhoneStateChangeListener extends PhoneStateListener {
       @Override
       public void onCallStateChanged(int state, String incomingNumber) {
           super.onCallStateChanged(state, incomingNumber);
           if (state == TelephonyManager.CALL_STATE_RINGING) {
               String phoneNumber =   incomingNumber;
           }
       }
   }
}
Jesbin MJ
quelle
Was sollen wir für Android P tun
Ahmad Arslan

Antworten:

336

Folgendes verwende ich dazu:

Manifest:

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

<!--This part is inside the application-->
    <receiver android:name=".CallReceiver" >
        <intent-filter>
            <action android:name="android.intent.action.PHONE_STATE" />
        </intent-filter>
        <intent-filter>
            <action android:name="android.intent.action.NEW_OUTGOING_CALL" />
        </intent-filter>
    </receiver>

Mein wiederverwendbarer Basisrufmelder

package com.gabesechan.android.reusable.receivers;

import java.util.Date;

import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.telephony.TelephonyManager;

public abstract class PhonecallReceiver extends BroadcastReceiver {

    //The receiver will be recreated whenever android feels like it.  We need a static variable to remember data between instantiations

    private static int lastState = TelephonyManager.CALL_STATE_IDLE;
    private static Date callStartTime;
    private static boolean isIncoming;
    private static String savedNumber;  //because the passed incoming is only valid in ringing


    @Override
    public void onReceive(Context context, Intent intent) {

        //We listen to two intents.  The new outgoing call only tells us of an outgoing call.  We use it to get the number.
        if (intent.getAction().equals("android.intent.action.NEW_OUTGOING_CALL")) {
            savedNumber = intent.getExtras().getString("android.intent.extra.PHONE_NUMBER");
        }
        else{
            String stateStr = intent.getExtras().getString(TelephonyManager.EXTRA_STATE);
            String number = intent.getExtras().getString(TelephonyManager.EXTRA_INCOMING_NUMBER);
            int state = 0;
            if(stateStr.equals(TelephonyManager.EXTRA_STATE_IDLE)){
                state = TelephonyManager.CALL_STATE_IDLE;
            }
            else if(stateStr.equals(TelephonyManager.EXTRA_STATE_OFFHOOK)){
                state = TelephonyManager.CALL_STATE_OFFHOOK;
            }
            else if(stateStr.equals(TelephonyManager.EXTRA_STATE_RINGING)){
                state = TelephonyManager.CALL_STATE_RINGING;
            }


            onCallStateChanged(context, state, number);
        }
    }

    //Derived classes should override these to respond to specific events of interest
    protected abstract void onIncomingCallReceived(Context ctx, String number, Date start);
    protected abstract void onIncomingCallAnswered(Context ctx, String number, Date start);
    protected abstract void onIncomingCallEnded(Context ctx, String number, Date start, Date end);

    protected abstract void onOutgoingCallStarted(Context ctx, String number, Date start);      
    protected abstract void onOutgoingCallEnded(Context ctx, String number, Date start, Date end);

    protected abstract void onMissedCall(Context ctx, String number, Date start);

    //Deals with actual events

    //Incoming call-  goes from IDLE to RINGING when it rings, to OFFHOOK when it's answered, to IDLE when its hung up
    //Outgoing call-  goes from IDLE to OFFHOOK when it dials out, to IDLE when hung up
    public void onCallStateChanged(Context context, int state, String number) {
        if(lastState == state){
            //No change, debounce extras
            return;
        }
        switch (state) {
            case TelephonyManager.CALL_STATE_RINGING:
                isIncoming = true;
                callStartTime = new Date();
                savedNumber = number;
                onIncomingCallReceived(context, number, callStartTime);
                break;
            case TelephonyManager.CALL_STATE_OFFHOOK:
                //Transition of ringing->offhook are pickups of incoming calls.  Nothing done on them
                if(lastState != TelephonyManager.CALL_STATE_RINGING){
                    isIncoming = false;
                    callStartTime = new Date();
                    onOutgoingCallStarted(context, savedNumber, callStartTime);                     
                }
                else
                {
                    isIncoming = true;
                    callStartTime = new Date();
                    onIncomingCallAnswered(context, savedNumber, callStartTime); 
                }

                break;
            case TelephonyManager.CALL_STATE_IDLE:
                //Went to idle-  this is the end of a call.  What type depends on previous state(s)
                if(lastState == TelephonyManager.CALL_STATE_RINGING){
                    //Ring but no pickup-  a miss
                    onMissedCall(context, savedNumber, callStartTime);
                }
                else if(isIncoming){
                    onIncomingCallEnded(context, savedNumber, callStartTime, new Date());                       
                }
                else{
                    onOutgoingCallEnded(context, savedNumber, callStartTime, new Date());                                               
                }
                break;
        }
        lastState = state;
    }
}

Um es dann zu verwenden, leiten Sie einfach eine Klasse daraus ab und implementieren Sie einige einfache Funktionen, je nachdem, welche Aufruftypen Sie interessieren:

public class CallReceiver extends PhonecallReceiver {

    @Override
    protected void onIncomingCallReceived(Context ctx, String number, Date start)
    {
        //
    }

    @Override
    protected void onIncomingCallAnswered(Context ctx, String number, Date start)
    {
        //
    }

    @Override
    protected void onIncomingCallEnded(Context ctx, String number, Date start, Date end)
    {
        //
    }

    @Override
    protected void onOutgoingCallStarted(Context ctx, String number, Date start)
    {
        //
    } 

    @Override 
    protected void onOutgoingCallEnded(Context ctx, String number, Date start, Date end)
    {
        //
    }

    @Override
    protected void onMissedCall(Context ctx, String number, Date start)
    {
        //
    }

}

Außerdem sehen Sie eine Beschreibung, warum der Code so ist, wie er in meinem Blog ist . Hauptlink: https://gist.github.com/ftvs/e61ccb039f511eb288ee

BEARBEITEN: Auf einfacheren Code aktualisiert, da ich die Klasse für meinen eigenen Gebrauch überarbeitet habe

Gabe Sechan
quelle
2
Dieser Code zeigt nichts an. Sie werden angerufen, wenn ein ausgehender Anruf beginnt / endet, und Sie erhalten die Nummer, die Startzeit und die Endzeit. Es ist Ihre Aufgabe, es tatsächlich anzuzeigen, weil ich nicht wissen kann, wie Sie das wollen.
Gabe Sechan
3
@ GabeSechan: Super! Können Sie mich bitte anleiten, mit der Situation des Wartens auf einen Anruf umzugehen?
Mehul Joisar
6
Nur um das hinzuzufügen, es funktionierte nicht, wenn die App nicht im Vordergrund oder Hintergrund war, bis ich dies im Empfänger hinzufügte: "android: enabled =" true "
Rajat Sharma
1
Statische Variablen bleiben bestehen, bis die Anwendung nicht mehr über genügend Arbeitsspeicher verfügt (was sehr lange dauern kann, je nachdem, ob Dienste ausgeführt werden und die allgemeinen Speicherbedingungen des Telefons). Aber ja, sie können verloren gehen. Sie können es auf die Festplatte schreiben, z. B. über eine gemeinsame Voreinstellung. Dies kann jedoch auch zu falschen Ergebnissen führen. In einigen Fällen, z. B. beim Neustart des Telefons, können Sie Ihre Daten nicht ordnungsgemäß löschen. Für meinen Anwendungsfall waren die seltenen Null- und Datenverluste besser als falsche Daten. Fühlen Sie sich frei, damit zu Ihren Bedürfnissen zu drehen.
Gabe Sechan
1
@GabeSechan: Es scheint einen Fehler zu geben. lastState sollte nicht initialisiert werden CALL_STATE_IDLE. Ich verpasse nur wenige Anrufe, wenn meine App im aktuellen Status beendet wird RINGING. Denn wenn es beim Beenden des IDLEAnrufs erneut wird , wird die statische Variable neu initialisiert CALL_STATE_IDLEund es wird entprellt, nichts zu tun. Wir verlieren also den Verweis auf lastState.
Heisenberg
23
private MyPhoneStateListener phoneStateListener = new MyPhoneStateListener();

sich registrieren

TelephonyManager telephonyManager = (TelephonyManager) getSystemService(TELEPHONY_SERVICE);
telephonyManager.listen(phoneStateListener, PhoneStateListener.LISTEN_CALL_STATE);

und abmelden

TelephonyManager telephonyManager = (TelephonyManager) getSystemService(TELEPHONY_SERVICE);
telephonyManager.listen(phoneStateListener, PhoneStateListener.LISTEN_NONE);
Stinepike
quelle
Wo soll ich das in der Hauptaktivität verwenden?
Jesbin MJ
Platzieren Sie dies in der Klasse, in der Sie die Änderung abhören. Normalerweise werden Register in oncreate erstellt und in ondestroy abgemeldet. Deklarieren Sie das Objekt global in der Klasse
stinepike
Diese Option erfordert keine Berechtigungen.
Mike
Während Gabes Lösung besser für aufdringlichere Funktionen geeignet ist, z. B. für eine Viber-App, ist dies die beste Lösung für diejenigen, die einfach auf Benutzeraktionen reagieren müssen, wenn sie einen Anruf tätigen. Das Anfordern einer Laufzeitberechtigung in solchen Fällen ist höchstwahrscheinlich ein Overkill und wird vom Benutzer möglicherweise nicht gut aufgenommen.
Atmosphäre
1
Ich möchte etwas tun, wenn ein Anruf kommt, wie mit diesem Code zu tun ist.
Noor Hossain
14

Mit Android P - Api Level 28: Sie benötigen die Berechtigung READ_CALL_LOG

Eingeschränkter Zugriff auf Anrufprotokolle

Android P bewegt die CALL_LOG, READ_CALL_LOG, WRITE_CALL_LOGund PROCESS_OUTGOING_CALLSBerechtigungen aus der PHONEBerechtigungsgruppe in den neuenCALL_LOG Berechtigungsgruppe. Diese Gruppe bietet Benutzern eine bessere Kontrolle und Sichtbarkeit für Apps, die Zugriff auf vertrauliche Informationen zu Telefonanrufen benötigen, z. B. das Lesen von Anruflisten und das Identifizieren von Telefonnummern.

Um Zahlen aus der Absichtsaktion PHONE_STATE zu lesen, benötigen Sie sowohl die READ_CALL_LOGBerechtigung als auch die READ_PHONE_STATEBerechtigung . Zum Lesen von Zahlen onCallStateChanged()benötigen Sie READ_CALL_LOGnur noch die Berechtigung. Sie benötigen die READ_PHONE_STATEErlaubnis nicht mehr .

atasoyh
quelle
für diejenigen , die nur das Hinzufügen sind READ_CALL_LOGin AndroidManifest.xmlFokus in eine Berechtigungsanfrage auf Hinzufügen MainActivity.
Piyush
13

UPDATE: Der wirklich großartige Code von Gabe Sechan funktioniert nicht mehr, es sei denn, Sie fordern den Benutzer ausdrücklich auf, die erforderlichen Berechtigungen zu erteilen. Hier ist ein Code, den Sie in Ihre Hauptaktivität einfügen können, um diese Berechtigungen anzufordern:

    if (getApplicationContext().checkSelfPermission(Manifest.permission.READ_PHONE_STATE)
            != PackageManager.PERMISSION_GRANTED) {
        // Permission has not been granted, therefore prompt the user to grant permission
        ActivityCompat.requestPermissions(this,
                new String[]{Manifest.permission.READ_PHONE_STATE},
                MY_PERMISSIONS_REQUEST_READ_PHONE_STATE);
    }

    if (getApplicationContext().checkSelfPermission(Manifest.permission.PROCESS_OUTGOING_CALLS)
            != PackageManager.PERMISSION_GRANTED) {
        // Permission has not been granted, therefore prompt the user to grant permission
        ActivityCompat.requestPermissions(this,
                new String[]{Manifest.permission.PROCESS_OUTGOING_CALLS},
                MY_PERMISSIONS_REQUEST_PROCESS_OUTGOING_CALLS);
    }

AUCH: Wie in einem Kommentar unter Gabes Beitrag erwähnt , müssen Sie android:enabled="truedem Empfänger einen kleinen Codeausschnitt hinzufügen , um eingehende Anrufe zu erkennen, wenn die App derzeit nicht im Vordergrund ausgeführt wird:

    <!--This part is inside the application-->
    <receiver android:name=".CallReceiver" android:enabled="true">
        <intent-filter>
            <action android:name="android.intent.action.PHONE_STATE" />
        </intent-filter>
        <intent-filter>
            <action android:name="android.intent.action.NEW_OUTGOING_CALL" />
        </intent-filter>
    </receiver>
topherPedersen
quelle
Was ist, wenn die Anwendung keine Aktivität und nur den Rundfunkempfänger und einen Dienst hat? Wo schreiben wir dann diesen Code, um die Erlaubnis des Benutzers zu erhalten, da der Rundfunkempfänger erst aufgerufen wird, wenn diese Erlaubnis erteilt wurde.
user2779311
2
Sie benötigen mindestens eine MainActivity, auch wenn diese nur einmal geöffnet ist. Nehmen Sie zum Beispiel meine Anrufsperr-App RoboStop: Wenn der Benutzer die App zum ersten Mal herunterlädt und dann auf das App-Symbol klickt, um die App zu starten, wird er aufgefordert, meiner App die erforderlichen Berechtigungen zu erteilen. Die App verfügt auch über eine Schaltfläche zum Aktivieren / Deaktivieren der Anrufsperre. Der Benutzer muss die App / Aktivität jedoch nicht erneut starten. Die Anrufsperre erfolgt im Hintergrund, ohne dass der Benutzer die App / Aktivität erneut starten muss.
TopherPedersen
Diejenigen, die Schwierigkeiten haben, dies umzusetzen, folgen diesem Tutorial studytutorial.in/…
Prasath
5

Dies kann Ihnen helfen und auch die erforderliche Berechtigung hinzufügen

public class PhoneListener extends PhoneStateListener
{
    private Context context;
    public static String getincomno;

    public PhoneListener(Context c) {
        Log.i("CallRecorder", "PhoneListener constructor");
        context = c;
    }

    public void onCallStateChanged (int state, String incomingNumber)
    {

        if(!TextUtils.isEmpty(incomingNumber)){
        // here for Outgoing number make null to get incoming number
        CallBroadcastReceiver.numberToCall = null;
        getincomno = incomingNumber;
        }

        switch (state) {
        case TelephonyManager.CALL_STATE_IDLE:

            break;
        case TelephonyManager.CALL_STATE_RINGING:
            Log.d("CallRecorder", "CALL_STATE_RINGING");
            break;
        case TelephonyManager.CALL_STATE_OFFHOOK:

            break;
        }
    }
}
Ankitkumar Makwana
quelle
2
das scheint in Ordnung zu sein. Aber wie kann ich es aus Aktivität verwenden? Bitte sagen Sie mir Details
Amir
2

Hier ist eine einfache Methode, mit der die Verwendung PhonestateListenerund andere Komplikationen vermieden werden können.
Also hier erhalten wir die 3 Ereignisse von Android wie RINGING, OFFHOOKund IDLE. Und um alle möglichen Zustand des Anrufs zu bekommen, müssen wir unsere eigenen Zustände wie definieren RINGING, OFFHOOK, IDLE, FIRST_CALL_RINGING, SECOND_CALL_RINGING. Es kann alle Zustände in einem Telefonanruf verarbeiten.
Bitte denken Sie so, dass wir Ereignisse von Android empfangen und unsere Bereitschaftszustände definieren. Siehe den Code.

public class CallListening  extends BroadcastReceiver {
    private static final String TAG ="broadcast_intent";
    public static String incoming_number;
    private String current_state,previus_state,event;
    public static Boolean dialog= false;
    private Context context;
    private SharedPreferences sp,sp1;
    private SharedPreferences.Editor spEditor,spEditor1;
    public void onReceive(Context context, Intent intent) {
        //Log.d("intent_log", "Intent" + intent);
        dialog=true;
        this.context = context;
        event = intent.getStringExtra(TelephonyManager.EXTRA_STATE);
        incoming_number = intent.getStringExtra(TelephonyManager.EXTRA_INCOMING_NUMBER);
        Log.d(TAG, "The received event : "+event+", incoming_number : " + incoming_number);
        previus_state = getCallState(context);
        current_state = "IDLE";
        if(incoming_number!=null){
            updateIncomingNumber(incoming_number,context);
        }else {
            incoming_number=getIncomingNumber(context);
        }
        switch (event) {
            case "RINGING":
                Log.d(TAG, "State : Ringing, incoming_number : " + incoming_number);
            if((previus_state.equals("IDLE")) || (previus_state.equals("FIRST_CALL_RINGING"))){
                    current_state ="FIRST_CALL_RINGING";
                }
                if((previus_state.equals("OFFHOOK"))||(previus_state.equals("SECOND_CALL_RINGING"))){
                    current_state = "SECOND_CALL_RINGING";
                }

                break;
            case "OFFHOOK":
                Log.d(TAG, "State : offhook, incoming_number : " + incoming_number);
                if((previus_state.equals("IDLE")) ||(previus_state.equals("FIRST_CALL_RINGING")) || previus_state.equals("OFFHOOK")){
                    current_state = "OFFHOOK";
                }
                if(previus_state.equals("SECOND_CALL_RINGING")){
                    current_state ="OFFHOOK";
                    startDialog(context);
                }
                break;
            case "IDLE":
                Log.d(TAG, "State : idle and  incoming_number : " + incoming_number);
                if((previus_state.equals("OFFHOOK")) || (previus_state.equals("SECOND_CALL_RINGING")) || (previus_state.equals("IDLE"))){
                    current_state="IDLE";
                }
                if(previus_state.equals("FIRST_CALL_RINGING")){
                    current_state = "IDLE";
                    startDialog(context);
                }
                updateIncomingNumber("no_number",context);
                Log.d(TAG,"stored incoming number flushed");
                break;
        }
        if(!current_state.equals(previus_state)){
            Log.d(TAG, "Updating  state from "+previus_state +" to "+current_state);
            updateCallState(current_state,context);

        }
    }
    public void startDialog(Context context) {
        Log.d(TAG,"Starting Dialog box");
        Intent intent1 = new Intent(context, NotifyHangup.class);
        intent1.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
        context.startActivity(intent1);

    }
    public void updateCallState(String state,Context context){
        sp = PreferenceManager.getDefaultSharedPreferences(context);
        spEditor = sp.edit();
        spEditor.putString("call_state", state);
        spEditor.commit();
        Log.d(TAG, "state updated");

    }
    public void updateIncomingNumber(String inc_num,Context context){
        sp = PreferenceManager.getDefaultSharedPreferences(context);
        spEditor = sp.edit();
        spEditor.putString("inc_num", inc_num);
        spEditor.commit();
        Log.d(TAG, "incoming number updated");
    }
    public String getCallState(Context context){
        sp1 = PreferenceManager.getDefaultSharedPreferences(context);
        String st =sp1.getString("call_state", "IDLE");
        Log.d(TAG,"get previous state as :"+st);
        return st;
    }
    public String getIncomingNumber(Context context){
        sp1 = PreferenceManager.getDefaultSharedPreferences(context);
        String st =sp1.getString("inc_num", "no_num");
        Log.d(TAG,"get incoming number as :"+st);
        return st;
    }
}
ARUNBALAN NV
quelle
0

@ Gabe Sechan, danke für deinen Code. Es funktioniert gut mit Ausnahme deronOutgoingCallEnded() . Es wird nie ausgeführt. Testtelefone sind Samsung S5 & Trendy. Ich denke, es gibt 2 Fehler.

1: Ein Paar Klammern fehlt.

case TelephonyManager.CALL_STATE_IDLE: 
    // Went to idle-  this is the end of a call.  What type depends on previous state(s)
    if (lastState == TelephonyManager.CALL_STATE_RINGING) {
        // Ring but no pickup-  a miss
        onMissedCall(context, savedNumber, callStartTime);
    } else {
        // this one is missing
        if(isIncoming){
            onIncomingCallEnded(context, savedNumber, callStartTime, new Date());                       
        } else {
            onOutgoingCallEnded(context, savedNumber, callStartTime, new Date());                                               
        }
    }
    // this one is missing
    break;

2: lastStatewird nicht aktualisiert, statewenn es am Ende der Funktion ist. Es sollte in der ersten Zeile dieser Funktion durch ersetzt werden

public void onCallStateChanged(Context context, int state, String number) {
    int lastStateTemp = lastState;
    lastState = state;
    // todo replace all the "lastState" by lastStateTemp from here.
    if (lastStateTemp  == state) {
        //No change, debounce extras
        return;
    }
    //....
}

Zusätzlich habe ich lastStateund savedNumberin gemeinsame Vorlieben gesetzt, wie Sie vorgeschlagen haben.

Habe es gerade mit den obigen Änderungen getestet. Fehler zumindest auf meinen Handys behoben.

Diiiiii
quelle
0

Bitte verwenden Sie den folgenden Code. Es wird Ihnen helfen, die eingehende Nummer mit anderen Anrufdetails zu erhalten.

activity_main.xml

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity" >

<TextView
    android:id="@+id/call"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:layout_centerHorizontal="true"
    android:layout_centerVertical="true"
    android:text="@string/hello_world" />

</RelativeLayout>

MainActivity.java

public class MainActivity extends Activity {

private static final int MISSED_CALL_TYPE = 0;
private TextView txtcall;

@Override
    protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);

    txtcall = (TextView) findViewById(R.id.call);

    StringBuffer sb = new StringBuffer();
    Cursor managedCursor = managedQuery(CallLog.Calls.CONTENT_URI, null,
            null, null, null);
    int number = managedCursor.getColumnIndex(CallLog.Calls.NUMBER);
    int type = managedCursor.getColumnIndex(CallLog.Calls.TYPE);
    int date = managedCursor.getColumnIndex(CallLog.Calls.DATE);
    int duration = managedCursor.getColumnIndex(CallLog.Calls.DURATION);
    sb.append("Call Details :");
    while (managedCursor.moveToNext()) {
        String phNumber = managedCursor.getString(number);
        String callType = managedCursor.getString(type);
        String callDate = managedCursor.getString(date);
        Date callDayTime = new Date(Long.valueOf(callDate));
        String callDuration = managedCursor.getString(duration);
        String dir = null;
        int dircode = Integer.parseInt(callType);
        switch (dircode) {

        case CallLog.Calls.OUTGOING_TYPE:
            dir = "OUTGOING";
            break;

        case CallLog.Calls.INCOMING_TYPE:
            dir = "INCOMING";
            break;

        case CallLog.Calls.MISSED_TYPE:
            dir = "MISSED";
            break;
        }
        sb.append("\nPhone Number:--- " + phNumber + " \nCall Type:--- "
                + dir + " \nCall Date:--- " + callDayTime
                + " \nCall duration in sec :--- " + callDuration);
        sb.append("\n----------------------------------");
    }
    managedCursor.close();
    txtcall.setText(sb);
}

@Override
public boolean onCreateOptionsMenu(Menu menu) {
    // Inflate the menu; this adds items to the action bar if it is present.
    getMenuInflater().inflate(R.menu.activity_main, menu);
    return true;
}

} 

und in Ihrer offensichtlichen Anfrage nach folgenden Berechtigungen:

<uses-permission android:name="android.permission.READ_CONTACTS"/>
<uses-permission android:name="android.permission.READ_LOGS"/>
user2173696
quelle
Mit READ_LOGS wird Ihre App aus dem Play Store verbannt
Duna
0

Sie benötigen einen BroadcastReceiver für ACTION_PHONE_STATE_CHANGEDDies ruft Ihren Empfänger an, wenn sich der Telefonstatus von Leerlauf, Klingeln, Abheben vom vorherigen Wert und dem neuen Wert, den Sie erkennen können, wenn es sich um einen eingehenden / ausgehenden Anruf handelt, ändert.

Erforderliche Erlaubnis wäre:

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

Wenn Sie jedoch auch EXTRA_INCOMING_NUMBER in dieser Sendung empfangen möchten, benötigen Sie eine andere Berechtigung: "android.permission.READ_CALL_LOG"

Und der Code ungefähr so:

val receiver: BroadcastReceiver = object : BroadcastReceiver() {
    override fun onReceive(context: Context, intent: Intent) {
        Log.d(TAG, "onReceive")
    }
}

override fun onResume() {
    val filter = IntentFilter()
    filter.addAction("android.intent.action.PHONE_STATE")
    registerReceiver(receiver, filter)
    super.onResume()
}

override fun onPause() {
    unregisterReceiver(receiver)
    super.onPause()
}

und in der Empfängerklasse können wir den aktuellen Status erhalten, indem wir die Absicht wie folgt lesen:

intent.extras["state"]

Das Ergebnis von Extras könnte sein:

RINGING -> Wenn Ihr Telefon klingelt

OFFHOOK -> Wenn Sie mit jemandem sprechen (eingehender oder ausgehender Anruf)

LEERLAUF -> wenn der Anruf beendet wurde (eingehender oder ausgehender Anruf)

Bei PHONE_STATE-Broadcasts müssen wir weder die Berechtigung PROCESS_OUTGOING_CALLS noch die veraltete Aktion NEW_OUTGOING_CALL verwenden.

FarshidABZ
quelle