How to detect when phone is answered or rejected

The question:

I managed to prepare an activity when the phone is ringing. Now I need to know how to cancel this activity, when I answer the phone or I reject the call.Do I call EXTRA_STATE_IDLE or EXTRA_STATE_OFFHOOK ?

Any ideas?


    <receiver android:name=".IncomingBroadcastReceiver">
            <action android:name="android.intent.action.PHONE_STATE" />

IncomingBroadcastReceiver java Class

public class IncomingBroadcastReceiver extends BroadcastReceiver {
    public void onReceive(Context context, Intent intent) {
        String state = intent.getStringExtra(TelephonyManager.EXTRA_STATE);
        // If an incoming call arrives
        if (state.equals(TelephonyManager.EXTRA_STATE_RINGING)) { //Did my work }

The Solutions:

Below are the methods you can try. The first solution is probably the best. Try others if the first one doesn’t work. Senior developers aren’t just copying/pasting – they read the methods carefully & apply them wisely to each case.

Method 1

The above answer is completely wrong in case of outgoing calls. In Android there is no way by which one detect whether the call was actually answered (in case of outgoing calls). The moment you dial a number, the off_hook state is fired. This is one of the drawbacks of Android programming.

Method 2

in your onReceive:

PhoneStateChangeListener pscl = new PhoneStateChangeListener();
TelephonyManager tm = (TelephonyManager)this.getSystemService(Context.TELEPHONY_SERVICE);
tm.listen(pscl, PhoneStateListener.LISTEN_CALL_STATE);

separate class:

private class PhoneStateChangeListener extends PhoneStateListener {
    public static boolean wasRinging;
    String LOG_TAG = "PhoneListener";
    public void onCallStateChanged(int state, String incomingNumber) {
            case TelephonyManager.CALL_STATE_RINGING:
                 Log.i(LOG_TAG, "RINGING");
                 wasRinging = true;
            case TelephonyManager.CALL_STATE_OFFHOOK:
                 Log.i(LOG_TAG, "OFFHOOK");

                 if (!wasRinging) {
                     // Start your new activity
                 } else {
                     // Cancel your old activity

                 // this should be the last piece of code before the break
                 wasRinging = true;
            case TelephonyManager.CALL_STATE_IDLE:
                 Log.i(LOG_TAG, "IDLE");
                 // this should be the last piece of code before the break
                 wasRinging = false;

All you need to do is write some code to check if the previous state was ‘ringing’.
If the current state is idle and the previous state was ringing, they cancelled the call.
If the current state is offhook and the previous state was ringing, they answered the call.

Method 3

Following are the states which it goes through in different scenarios:

1) Answering Received call

CALL_STATE_RINGING => CALL_STATE_OFFHOOK (After Answering call) => CALL_STATE_IDLE (After End call) 

2) Rejecting / Not Answering (Missed) Received call


3) Dialing call

CALL_STATE_OFFHOOK (After dialing) => CALL_STATE_IDLE (After End call) 


  int prev_state=0;

  public class CustomPhoneStateListener extends PhoneStateListener {  

        private static final String TAG = "CustomPhoneStateListener";  

        public void onCallStateChanged(int state, String incomingNumber){  

            if(incomingNumber!=null&&incomingNumber.length()>0) incoming_nr=incomingNumber;   

                case TelephonyManager.CALL_STATE_RINGING:  
                        Log.d(TAG, "CALL_STATE_RINGING");  
                case TelephonyManager.CALL_STATE_OFFHOOK:  
                Log.d(TAG, "CALL_STATE_OFFHOOK");  
                case TelephonyManager.CALL_STATE_IDLE:  
                    Log.d(TAG, "CALL_STATE_IDLE==>"+incoming_nr);  
                    NumberDatabase database=new NumberDatabase(mContext);  
                        //Answered Call which is ended  
                        //Rejected or Missed call  


In your receiver

onReceive(Context context, Intent intent) {  
        TelephonyManager telephony = (TelephonyManager)context.getSystemService(Context.TELEPHONY_SERVICE); //TelephonyManager object  
        CustomPhoneStateListener customPhoneListener = new CustomPhoneStateListener();  
        telephony.listen(customPhoneListener, PhoneStateListener.LISTEN_CALL_STATE);          //Register our listener with TelephonyManager  

        Bundle bundle = intent.getExtras();  
        String phoneNr= bundle.getString("incoming_number");  


Method 4

below is a code of detecting outgoing call by accessibility events –

Add a class which extends AccessibilityService in your projects –

public class CallDetection extends AccessibilityService {
public void onAccessibilityEvent(AccessibilityEvent event) {
    Log.d("myaccess","after lock");
    if (event.getEventType() == AccessibilityEvent.TYPE_WINDOW_CONTENT_CHANGED) {
        Log.d("myaccess","in window changed");
        AccessibilityNodeInfo info = event.getSource();
        if (info != null && info.getText() != null) {
            String duration = info.getText().toString();
            String zeroSeconds = String.format("%02d:%02d", new Object[]{Integer.valueOf(0), Integer.valueOf(0)});
            String firstSecond = String.format("%02d:%02d", new Object[]{Integer.valueOf(0), Integer.valueOf(1)});
            Log.d("myaccess","after calculation - "+ zeroSeconds + " --- "+ firstSecond + " --- " + duration);
            if (zeroSeconds.equals(duration) || firstSecond.equals(duration)) {
                Toast.makeText(getApplicationContext(),"Call answered",Toast.LENGTH_SHORT).show();
               // Your Code goes here

protected void onServiceConnected() {
    Toast.makeText(this,"Service connected",Toast.LENGTH_SHORT).show();
    AccessibilityServiceInfo info = new AccessibilityServiceInfo();
    info.eventTypes = AccessibilityEvent.TYPE_WINDOW_CONTENT_CHANGED;
    info.feedbackType = AccessibilityServiceInfo.FEEDBACK_GENERIC;
    info.notificationTimeout = 0;
    info.packageNames = null;

public void onInterrupt() {


But to get the function event.getSource() working you have to specify some of your service configuration through xml, so create a xml folder in your project and add a xml file called serviceconfig.xml (you can give any name you want.

The content of serviceconfig is below –

<accessibility-service xmlns:android=""

You can find more about serviceconfig in Here

Now add your service in you Manifest file like this –

<service android:name=".CallDetection"
            <action android:name="android.accessibilityservice.AccessibilityService" />
            android:resource="@xml/serviceconfig" />

And youre done, just run the app and go to Accessibility settings in your phone, you will find an option named as detection (or whatever name you have given as your service description), switch that on to give accesibility permissions for you app.

Now you will see a toast when call is answered.

you can Code any code you want in there, also you can call a callback function in your activity

Most important – Dont call your call window(android dialer window) untill the call is answered, otherwise this will not work.

Note – As android doesn’t provide any solution to detect if the call is answered or not, this is the best alternative i have made, hope it works for you.

Method 5

public class myService extends InCallService 
    // Here... :)
    @Override public void onCanAddCallChanged(boolean canAddCall) 

Method 6

To detect that a call is received, you can detect a “hello” voice. “hello” voice is the frequency (voice activity) outside of Call progress Frequency. For reference you can have a look at this datasheet part:

All methods was sourced from or, is licensed under cc by-sa 2.5, cc by-sa 3.0 and cc by-sa 4.0

Leave a Comment