Bagaimana cara mendeteksi panggilan masuk, di perangkat Android?

130

Saya mencoba membuat aplikasi seperti, ketika ada panggilan ke telepon saya ingin mendeteksi nomornya. Di bawah ini adalah yang saya coba, tetapi tidak mendeteksi panggilan masuk.

Saya ingin menjalankan MainActivitylatar belakang saya , bagaimana saya bisa melakukan itu?

Saya telah memberikan izin dalam manifestfile.

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

Apakah ada hal lain yang harus saya berikan dalam manifes?

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
sumber
apa yang harus kita lakukan untuk Android P
Ahmad Arslan

Jawaban:

336

Inilah yang saya gunakan untuk melakukan ini:

Nyata:

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

Detektor panggilan reusable base saya

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

Kemudian untuk menggunakannya, cukup ambil kelas darinya dan terapkan beberapa fungsi mudah, yang jenis panggilan apa pun yang Anda pedulikan:

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)
    {
        //
    }

}

Selain itu Anda dapat melihat Langgan yang saya lakukan pada mengapa kode itu seperti itu di blog saya . Tautan intisari: https://gist.github.com/ftvs/e61ccb039f511eb288ee

EDIT: Diperbarui ke kode yang lebih sederhana, karena saya telah mengerjakan ulang kelas untuk saya gunakan sendiri

Gabe Sechan
sumber
2
Kode ini tidak menampilkan apa pun. Apa yang dilakukannya adalah memanggil Anda ketika panggilan keluar dimulai / berakhir, dan memberikan Anda nomor, waktu mulai, dan waktu selesai. Sebenarnya menampilkan itu adalah pekerjaan Anda, karena saya tidak tahu bagaimana Anda ingin itu dilakukan.
Gabe Sechan
3
@GabeSechan: Luar Biasa! bisakah Anda membimbing saya untuk menangani situasi panggilan tunggu?
Mehul Joisar
6
Hanya untuk menambahkan ini, itu tidak berfungsi ketika aplikasi tidak di latar depan atau latar belakang sampai saya menambahkan ini di penerima: "android: enabled =" true "
Rajat Sharma
1
Variabel statis akan tetap ada sampai aplikasi dikeluarkan dari memori (yang bisa memakan waktu cukup lama, tergantung pada apakah layanan berjalan dan kondisi memori telepon umum). Tapi ya, mereka bisa hilang. Anda dapat menulis ke disk, katakan melalui preferensi bersama tetapi itu dapat menyebabkan Anda memiliki hasil yang salah juga - itu akan mencegah Anda dari data Anda dibersihkan dengan benar dalam beberapa kasus, seperti sekitar reboot ponsel. Untuk kasus penggunaan saya, data nol dan hilang yang langka lebih baik daripada data yang salah. Jangan ragu untuk bermain-main dengan ini untuk kebutuhan Anda.
Gabe Sechan
1
@ GabeSechan: Sepertinya ada bug di dalamnya. lastState seharusnya tidak diinisialisasi ke CALL_STATE_IDLE. Saya kehilangan beberapa panggilan saat aplikasi saya terbunuh saat keadaan saat ini RINGING. Karena ketika menjadi IDLElagi pada panggilan berakhir, variabel statis diinisialisasi ulang ke CALL_STATE_IDLEdan itu melakukan debounces tidak melakukan apa pun. Jadi kami kehilangan referensi lastState.
Heisenberg
23
private MyPhoneStateListener phoneStateListener = new MyPhoneStateListener();

mendaftar

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

dan untuk membatalkan registrasi

TelephonyManager telephonyManager = (TelephonyManager) getSystemService(TELEPHONY_SERVICE);
telephonyManager.listen(phoneStateListener, PhoneStateListener.LISTEN_NONE);
stinepike
sumber
di mana saya harus menggunakan ini di mainaktivitas?
Jesbin MJ
letakkan ini di kelas di mana Anda mendengarkan perubahan .. biasanya register dilakukan di oncreate dan batalkan registrasi di ondestroy .. deklarasikan objek secara global di kelas
stinepike
Opsi ini tidak memerlukan izin.
Mike
sementara solusi Gabe lebih cocok untuk fitur yang lebih mengganggu yaitu aplikasi semacam Viber, ini adalah solusi terbaik bagi mereka yang membutuhkan untuk hanya bereaksi terhadap tindakan pengguna yang melakukan panggilan telepon. Meminta izin runtime dalam kasus seperti ini kemungkinan besar merupakan kerja keras dan mungkin tidak diterima dengan baik oleh pengguna.
bosphere
1
Saya ingin melakukan sesuatu, ketika ada panggilan, bagaimana hubungannya dengan kode ini?
Noor Hossain
14

Dengan Android P - Api Level 28: Anda harus mendapatkan izin READ_CALL_LOG

Akses terbatas ke log panggilan

Android P bergerak CALL_LOG, READ_CALL_LOG, WRITE_CALL_LOG, dan PROCESS_OUTGOING_CALLSizin dari PHONEkelompok izin ke yang baru CALL_LOGkelompok izin. Grup ini memberi pengguna kontrol dan visibilitas yang lebih baik ke aplikasi yang membutuhkan akses ke informasi sensitif tentang panggilan telepon, seperti membaca catatan panggilan telepon dan mengidentifikasi nomor telepon.

Untuk membaca angka dari tindakan niat PHONE_STATE, Anda memerlukan READ_CALL_LOGizin dan READ_PHONE_STATEizin . Untuk membaca angka onCallStateChanged(), Anda sekarang hanya perlu READ_CALL_LOGizin. Anda tidak lagi memerlukan READ_PHONE_STATEizin.

atasoyh
sumber
bagi mereka yang hanya menambahkan READ_CALL_LOGdalam AndroidManifest.xmlfokus pada menambahkan permintaan izin di MainActivity.
Piyush
13

PEMBARUAN: Kode yang sangat luar biasa yang diposting oleh Gabe Sechan tidak lagi berfungsi kecuali jika Anda secara eksplisit meminta pengguna untuk memberikan izin yang diperlukan. Berikut adalah beberapa kode yang dapat Anda tempatkan dalam aktivitas utama Anda untuk meminta izin ini:

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

JUGA: Seperti seseorang yang disebutkan dalam komentar di bawah posting Gabe , Anda harus menambahkan sedikit cuplikan kode android:enabled="true,, ke penerima untuk mendeteksi panggilan masuk saat aplikasi saat ini tidak berjalan di latar depan:

    <!--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
sumber
Bagaimana jika aplikasi tidak memiliki Kegiatan apa pun dan hanya penerima siaran dan layanan. Lalu di mana kita menulis kode ini untuk mendapatkan izin dari pengguna karena si penerima siaran tidak akan dipanggil sampai izin ini diberikan.
user2779311
2
Anda setidaknya memerlukan MainActivity meskipun hanya dibuka sekali. Ambil aplikasi pemblokiran panggilan saya RoboStop misalnya: Ketika pengguna mengunduh aplikasi untuk pertama kalinya, dan kemudian mengklik ikon aplikasi untuk meluncurkan aplikasi, mereka kemudian diminta untuk memberikan aplikasi saya izin yang diperlukan. Aplikasi ini juga dilengkapi tombol untuk mengaktifkan / menonaktifkan pemblokiran panggilan, tetapi pengguna tidak perlu meluncurkan aplikasi / aktivitas lagi, pemblokiran panggilan akan dilakukan di latar belakang tanpa pengguna harus meluncurkan aplikasi / aktivitas lagi.
topherPedersen
Mereka yang memiliki kesulitan untuk mengimplementasikan ini, ikuti tutorial ini studytutorial.in/…
Prasath
5

ini dapat membantu Anda dan juga menambahkan memerlukan izin

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
sumber
2
ini tampaknya baik-baik saja. Tetapi bagaimana saya bisa menggunakannya dari aktivitas? tolong beri tahu saya perincian
Amir
2

Berikut adalah metode sederhana yang dapat menghindari penggunaan PhonestateListenerdan komplikasi lainnya.
Jadi di sini kita menerima 3 acara dari android seperti RINGING, OFFHOOKdan IDLE. Dan untuk mendapatkan semua negara yang mungkin panggilan, kita perlu mendefinisikan negara kita sendiri seperti RINGING, OFFHOOK, IDLE, FIRST_CALL_RINGING, SECOND_CALL_RINGING. Itu dapat menangani setiap negara bagian dalam panggilan telepon.
Harap pikirkan cara kami menerima acara dari android dan kami akan menentukan status panggilan kami. Lihat kodenya.

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

@ Gabe Sechan, terima kasih untuk kode Anda. Ini berfungsi dengan baik kecuali onOutgoingCallEnded(). Itu tidak pernah dieksekusi. Ponsel penguji adalah Samsung S5 & Trendy. Ada 2 bug saya pikir.

1: sepasang tanda kurung tidak ada.

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: lastStatetidak diperbarui oleh statejika berada di akhir fungsi. Itu harus diganti ke baris pertama dari fungsi ini dengan

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

Tambahan saya telah memasukkan lastStatedan savedNumberke preferensi bersama seperti yang Anda sarankan.

Baru saja mengujinya dengan perubahan di atas. Bug diperbaiki setidaknya di ponsel saya.

Diiiiii
sumber
0

Silakan gunakan kode di bawah ini. Ini akan membantu Anda mendapatkan nomor yang masuk dengan detail panggilan lainnya.

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

} 

dan dalam permintaan nyata Anda untuk izin berikut:

<uses-permission android:name="android.permission.READ_CONTACTS"/>
<uses-permission android:name="android.permission.READ_LOGS"/>
pengguna2173696
sumber
READ_LOGS melakukannya sehingga aplikasi Anda dilarang dari play store
Duna
0

Anda memerlukan BroadcastReceiver untuk ACTION_PHONE_STATE_CHANGEDIni akan memanggil Anda diterima setiap kali keadaan telepon berubah dari idle, dering, lepas kendali jadi dari nilai sebelumnya dan nilai baru Anda dapat mendeteksi jika ini adalah panggilan masuk / keluar.

Izin yang diperlukan adalah:

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

Tetapi jika Anda juga ingin menerima EXTRA_INCOMING_NUMBER dalam siaran itu, Anda akan memerlukan izin lain: "android.permission.READ_CALL_LOG"

Dan kodenya kira-kira seperti ini:

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

dan di kelas penerima, kita bisa mendapatkan status saat ini dengan membaca maksud seperti ini:

intent.extras["state"]

hasil ekstra dapat berupa:

RINGING -> Jika telepon Anda berdering

OFFHOOK -> Jika Anda berbicara dengan seseorang (Panggilan Masuk atau Keluar)

IDLE -> jika panggilan berakhir (Panggilan masuk atau Keluar)

Dengan siaran PHONE_STATE, kami tidak perlu menggunakan izin PROCESS_OUTGOING_CALLS atau menghentikan tindakan NEW_OUTGOING_CALL.

FarshidABZ
sumber