Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
781 views
in Technique[技术] by (71.8m points)

broadcastreceiver - Cannot detect when outgoing call is answered in Android

To detect when an outgoing call is answered, I tried creating a PhoneStateListener and listening for TelephonyManager's CALL_STATE_RINGING, CALL_STATE_OFFHOOK, and CALL_STATE_IDLE, from this question, but it does not seem to work, as explained below.

First, I registered the following permission in the manifest:

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

Then, a BroadcastReceiver called OutCallLogger that catches the NEW_OUTGOING_CALL event whenever an outgoing call is made:

<receiver android:name=".listener.OutCallLogger">
    <intent-filter>
        <action android:name="android.intent.action.NEW_OUTGOING_CALL" />
    </intent-filter>
</receiver>

Next, my implementation of OutCallLogger. I set up a boolean called noCallListenerYet to avoid attaching a new PhoneStateListener to the TelephonyManager whenever onReceive() is invoked.

public class OutCallLogger extends BroadcastReceiver {

    private static boolean noCallListenerYet = true;

    @Override
    public void onReceive(final Context context, Intent intent) {
        number = intent.getStringExtra(Intent.EXTRA_PHONE_NUMBER);
        if (noCallListenerYet) {
            final TelephonyManager tm = (TelephonyManager) context.getSystemService(
                    Context.TELEPHONY_SERVICE);
            tm.listen(new PhoneStateListener() {
                @Override
                public void onCallStateChanged(int state, String incomingNumber) {
                    switch (state) {
                        case TelephonyManager.CALL_STATE_RINGING:
                            Log.d(This.LOG_TAG, "RINGING");
                            break;
                        case TelephonyManager.CALL_STATE_OFFHOOK:
                            Log.d(This.LOG_TAG, "OFFHOOK");
                            break;
                        case TelephonyManager.CALL_STATE_IDLE:
                            Log.d(This.LOG_TAG, "IDLE");
                            break;
                        default:
                            Log.d(This.LOG_TAG, "Default: " + state);
                            break;
                    }
                }
            }, PhoneStateListener.LISTEN_CALL_STATE);
            noCallListenerYet = false;
        }
    }

}

Now, when I make an outgoing call in my device, CALL_STATE_RINGING is NEVER invoked. I always only get printouts of "IDLE" to "OFFHOOK" when the other line starts ringing, nothing when the call is answered, and a printout of "IDLE" again when the call is ended.

How can I reliably detect when an outgoing call is answered in Android, or is that even possible?

Question&Answers:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

Since Android 5.0 this is possible for system apps. But you need to use the hidden Android API.

I got it to work like this:

<uses-permission android:name="android.permission.READ_PRECISE_PHONE_STATE" />
<receiver android:name=".listener.OutCallLogger">
    <intent-filter>
        <action android:name="android.intent.action.PRECISE_CALL_STATE" />
    </intent-filter>
</receiver>
public class OutCallLogger extends BroadcastReceiver {

    @Override
    public void onReceive(Context context, Intent intent) {
        switch (intent.getIntExtra(TelephonyManager.EXTRA_FOREGROUND_CALL_STATE, -2) {
            case PreciseCallState.PRECISE_CALL_STATE_IDLE:
                Log.d(This.LOG_TAG, "IDLE");
                break;
            case PreciseCallState.PRECISE_CALL_STATE_DIALING:
                Log.d(This.LOG_TAG, "DIALING");
                break;
            case PreciseCallState.PRECISE_CALL_STATE_ALERTING:
                Log.d(This.LOG_TAG, "ALERTING");
                break;
            case PreciseCallState.PRECISE_CALL_STATE_ACTIVE:
                Log.d(This.LOG_TAG, "ACTIVE");
                break;
        }
    }
}

You can find all possible call states in PreciseCallState.java and all extras that the intent contains in TelephonyRegistry.java.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...