Search code examples
androidandroid-intentandroid-contentprovidercontentobserver

distinguish between answered and unanswered outgoing calls


I want to find out if an outgoing call has been answered. Unfortunately, in the case of an outgoing call I see

Intent { act=android.intent.action.PHONE_STATE flg=0x10 (has extras) } extras:Bundle{ state => OFFHOOK; }Bundle
Intent { act=android.intent.action.PHONE_STATE flg=0x10 (has extras) } extras:Bundle{ state => IDLE; }Bundle

regardless of whether or not the call was answered.

How do I detect that an outgoing call is answered? (For both rooted and unrooted devices, please.)


Solution

  • In Android you can't distinguish between answered and unanswered outgoing calls using intent(but available on ios).

    My workaround: Check phone app log (see CallLog.Calls), if outgoing calls has time log is greater than 0, then it was answered.

        public static final int TIME_TO_WAIT_PHONE_LOG_UPDATE_MILISECOND = 2000;
        public static final int PHONE_CALL_SUCCESS = 0x00; // answered
        public static final int PHONE_CALL_FAILED = 0x01; // unanswered
    

    //

    private class PhoneCallListener extends PhoneStateListener {
    
                @Override
                public void onCallStateChanged(int state, String incomingNumber) {
                    if (TelephonyManager.CALL_STATE_OFFHOOK == state) {
                        // Calling not picked up
                        // Đang gọi chưa nhấc máy
                        Log.i(DEBUG_TAG, "OFFHOOK, num = " + incomingNumber);
                        isCalling = true;
                    }
    
                    if (TelephonyManager.CALL_STATE_IDLE == state) {
                        if (isCalling) {
                            // close
                            // Kết Thúc
                            Log.v(DEBUG_TAG, "CALL_STATE_IDLE, num = " + incomingNumber);
                            isCalling = false;
    
                            // Read the log to see if the other party can hear the machine or not
                            // Đọc log xem thử bên kia có nghe máy hay không
                            new Handler().postDelayed(new Runnable() {
    
                                @Override
                                public void run() {
                                    int result = getCallDetails();
    
                                    if (mOnCallFinishListener != null) {
                                        mOnCallFinishListener.onCallFinish(supporter, result);
                                    }
                                }
                            }, MikeMikeConfig.TIME_TO_WAIT_PHONE_LOG_UPDATE_MILISECOND);
                        }
                    }
                }
            }
    
    private int getCallDetails() { 
                int ret = 0;
    
                StringBuffer sb = new StringBuffer();
                Cursor managedCursor = activity.getContentResolver().query(CallLog.Calls.CONTENT_URI, null, null, null, /*null*/ CallLog.Calls.DEFAULT_SORT_ORDER);
                // on some phones (e.g. LG) null does not mean DEFAULT_SORT_ORDER which is "date DESC"
                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 Log :"); 
                //while (managedCursor.moveToNext()) { 
                    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(); textView.setText(sb); } 
    
                //Log.v(DEBUG_TAG, sb + "");
    
                    int call_duration = Integer.parseInt(callDuration);
                    Log.v(DEBUG_TAG, "duration = " + call_duration);
    
    
                    if (call_duration > 0) ret = MikeMikeConfig.PHONE_CALL_SUCCESS;
    
                    if (call_duration == 0) ret = MikeMikeConfig.PHONE_CALL_FAILED;
    
                    return ret;
            }