Android - How to detect outgoing call is answered or received?

Nooruddin Lakhani picture Nooruddin Lakhani · Oct 4, 2014 · Viewed 8.9k times · Source

Is there any way to detect outgoing call is successfully received or answered ? I am using Intent.ACTION_CALL for dialing a call and PhoneCallListener to find the state of a call when outgoing call answered but I couldn't have been achieving this. Is this possible in android ?

Answer

Mohammad Qandeel picture Mohammad Qandeel · Apr 26, 2016

After deeply working on this issue, I reached this conclusion:

  1. PhoneStateListener won't work for outgoing calls, it calls OFFHOOK instead of RINGING and OFFHOOK is never called on ANSWER.

  2. Using NotificationListenerService, you can listen to posted notifications related to outgoing calls. You can do something like the below code. The issue here is that I'm not able to get the notification text from some Samsung phones, also the text itself might change a lot from one phone to another. Also it requires API 18 and above.

    public class NotificationListener extends NotificationListenerService {
    
        private String TAG = this.getClass().getSimpleName();
    
        @Override
        public void onNotificationPosted(StatusBarNotification sbn) {
            Log.i(TAG, "Notification Posted");
            Log.i(TAG, sbn.getPackageName() +
                    "\t" + sbn.getNotification().tickerText +
                    "\t" + sbn.getNotification().extras.getString(Notification.EXTRA_TEXT);
    
            Bundle extras = sbn.getNotification().extras;
    
            if ("Ongoing call".equals(extras.getString(Notification.EXTRA_TEXT))) {
                startService(new Intent(this, ZajilService.class).setAction(ZajilService.ACTION_CALL_ANSWERED));
            } else if ("Dialing".equals(extras.getString(Notification.EXTRA_TEXT))) {
                startService(new Intent(this, ZajilService.class).setAction(ZajilService.ACTION_CALL_DIALING));
            }
        }
    
        @Override
        public void onNotificationRemoved(StatusBarNotification sbn) {
            Log.i(TAG, "********** onNotificationRemoved");
            Log.i(TAG, "ID :" + sbn.getId() + "\t" + sbn.getNotification().tickerText + "\t" + sbn.getPackageName());
        }
    }
    
  3. Using AccessibilityService, it is more basic than NotificationListenerService and I think it is supported by all APIs. But also using AccessibilityService, some phones don't publish useful events in case of call Answer. In most phones, an event wil be raised once the call answered, with call duration; Its printout looks like this:

onAccessibilityEvent EventType: TYPE_WINDOW_CONTENT_CHANGED; EventTime: 21715433; PackageName: com.android.incallui; MovementGranularity: 0; Action: 0 [ ClassName: android.widget.TextView; Text: []; ContentDescription: 0 minutes 0 seconds;

onAccessibilityEvent EventType: TYPE_WINDOW_CONTENT_CHANGED; EventTime: 21715533; PackageName: com.android.incallui; MovementGranularity: 0; Action: 0 [ ClassName: android.widget.TextView; Text: []; ContentDescription: 0 minutes 1 seconds;

  1. API 23 has a new class, Call. it has more detailed call states; STATE_ACTIVE. You can replace the default InCallUI of the phone by your own UI through InCallService I didn't try to use this yet, but anyway, it is just limited to API 23, Marshmallow.

As a conclusion, You need to build a solution combined with NotificationListener and AccessibilityService, in order to cover all phone, hopefully.