How to identify the ringing state of outgoing call

2020-03-26 10:51发布

问题:

In my app i want to identify whether the outgoing call state like waiting,received or rejected by other side. I searched a lot in these below links
Outgoing call status How to detect answered or rejected state in outgoing call,outgoing call information through android BroadcastReceiver,identify outgoing call connect event
But couldn'd find a proper answer.Plz help me.Thanx.

回答1:

I know its been a while but i hope to be helpful for someone still looking for a solution!

I recently had to work on a similar project where i needed to capture the ringing state of an outgoing call and the only way i could find was using the hidden Api of native dial-up App. This would only be possible for android > 5.0 because of the api changes. This was tested on Android 5.0.1, and worked like a charm. (p.s. you would need a rooted device for it to work, because you need to install your app as a System application (google how!) which will then be able to detect the outgoing call states).

For the record, PhoneStateListener doesn't work for detecting the outgoing call states as mentioned in many posts.

First, add this permission in the manifest file,

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

Then define you broadcastreceiver, (here is a sample code!)

import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.telephony.TelephonyManager;

public class MyBroadcastReceiver extends BroadcastReceiver
{
    @Override
    public void onReceive(Context context, final Intent intent)
    {
        switch (intent.getIntExtra("foreground_state", -2)) {
            case 0: //  PreciseCallState.PRECISE_CALL_STATE_IDLE:
                System.out.println("IDLE");
                break;
            case 3: //  PreciseCallState.PRECISE_CALL_STATE_DIALING:
                System.out.println("DIALING");
                break;
            case 4: //  PreciseCallState.PRECISE_CALL_STATE_ALERTING:
                System.out.println("ALERTING");
                break;
            case 1: //  PreciseCallState.PRECISE_CALL_STATE_ACTIVE:
                System.out.println("ACTIVE");
                break;
        }

    }
} 

I replace some of the constants with their values because i saw alot of confusion among the folks unfamiliar with the concept of reflection (for ease). Alerting is basically the state when receiver is actually ringing! and that does not include the call setup time!.



回答2:

I had a similar issue. I wanted to detect some states of outgoing calls. I solved the issue by using visualizer class in android. It can return you with a Fourier transform of the current audio playing on the speaker. Using the type of audio being played(small beeping on the front speaker) you can determine the state of out-going call. For example you can know whether the phone has started ringing on the receiver or not. When ever visualizer return non-zero samples it is a yes.

Background audio wont disturb you because during a phone call the caller app shuts down all other audio.

Wait for status off_hook and then start your visualizer class



回答3:

Try this, Look in else part and do changes there, it will work.

public class CallBr extends BroadcastReceiver {
        Bundle bundle;
        String state;
        String inCall, outCall;
        public boolean wasRinging = false;

        @Override
        public void onReceive(Context context, Intent intent) {
            if (intent.getAction().equals(ACTION_IN)) {
                if ((bundle = intent.getExtras()) != null) {
                    state = bundle.getString(TelephonyManager.EXTRA_STATE);
                    if (state.equals(TelephonyManager.EXTRA_STATE_RINGING)) {
                        inCall = bundle.getString(TelephonyManager.EXTRA_INCOMING_NUMBER);
                        wasRinging = true;
                        Toast.makeText(context, "IN : " + inCall, Toast.LENGTH_LONG).show();
                    } else if (state.equals(TelephonyManager.EXTRA_STATE_OFFHOOK)) {
                        if (wasRinging == true) {

                            Toast.makeText(context, "ANSWERED", Toast.LENGTH_LONG).show();

                            String out = new SimpleDateFormat("dd-MM-yyyy hh-mm-ss").format(new Date());
                            File sampleDir = new File(Environment.getExternalStorageDirectory(), "/TestRecordingDasa1");
                            if (!sampleDir.exists()) {
                                sampleDir.mkdirs();
                            }
                            String file_name = "Record";
                            try {
                                audiofile = File.createTempFile(file_name, ".amr", sampleDir);
                            } catch (IOException e) {
                                e.printStackTrace();
                            }
                            String path = Environment.getExternalStorageDirectory().getAbsolutePath();

                            recorder = new MediaRecorder();
//                          recorder.setAudioSource(MediaRecorder.AudioSource.VOICE_CALL);

                            recorder.setAudioSource(MediaRecorder.AudioSource.VOICE_COMMUNICATION);
                            recorder.setOutputFormat(MediaRecorder.OutputFormat.AMR_NB);
                            recorder.setAudioEncoder(MediaRecorder.AudioEncoder.AMR_NB);
                            recorder.setOutputFile(audiofile.getAbsolutePath());
                            try {
                                recorder.prepare();
                            } catch (IllegalStateException e) {
                                e.printStackTrace();
                            } catch (IOException e) { 
                                e.printStackTrace();
                            }
                            recorder.start();
                            recordstarted = true;
                        }
                    } else if (state.equals(TelephonyManager.EXTRA_STATE_IDLE)) {
                        wasRinging = false;
                        Toast.makeText(context, "REJECT || DISCO", Toast.LENGTH_LONG).show();
                        if (recordstarted) {
                            recorder.stop();
                            recordstarted = false;
                        }
                    }
                }
            } else if (intent.getAction().equals(ACTION_OUT)) {
                if ((bundle = intent.getExtras()) != null) {
                    outCall = intent.getStringExtra(Intent.EXTRA_PHONE_NUMBER);
                    Toast.makeText(context, "OUT : " + outCall, Toast.LENGTH_LONG).show();
                }
            }
        }
    }


回答4:

Try this, You can use PhoneListener extends to PhoneStateListener.

import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.telephony.PhoneStateListener;
import android.telephony.TelephonyManager;

public class ListenToCallState extends BroadcastReceiver {

// private LoadProfImage mProfile;
@Override
public void onReceive(Context context, Intent intent) {
    // TODO Auto-generated method stub
    // mProfile = new LoadProfImage(context);

    PhoneListener phoneListener = new PhoneListener(context);
    TelephonyManager telephony = (TelephonyManager) context
            .getSystemService(Context.TELEPHONY_SERVICE);
    telephony.listen(phoneListener, PhoneStateListener.LISTEN_CALL_STATE);

}

class PhoneListener extends PhoneStateListener {
    private Context context;

    public PhoneListener(Context context) {
        // TODO Auto-generated constructor stub
        this.context = context;
    }

    public void onCallStateChanged(int state, String incomingNumber) {

        switch (state) {

        case TelephonyManager.CALL_STATE_IDLE:
                            //Do your stuff
            break;

        case TelephonyManager.CALL_STATE_RINGING:
                             //Do your stuff
            break;

        case TelephonyManager.CALL_STATE_OFFHOOK:
                              //Do your stuff
            break;

        }
    }
}

}