如何在安卓系统中识别呼出电话的响铃状态

4
4个回答

2

我知道已经过了一段时间,但我希望对仍在寻找解决方案的人有所帮助!

最近我需要处理一个类似的项目,在其中我需要捕获呼出电话的响铃状态,唯一的方法是使用原生拨号应用程序的隐藏API。这只适用于Android 5.0以上版本,因为API发生了变化。此方法在Android 5.0.1上测试通过,效果非常好。(注意:您需要将您的应用程序安装为系统应用程序(请搜索“如何将应用程序安装为系统应用程序”),才能检测到呼出电话的状态)。

请注意,许多帖子中提到的PhoneStateListener无法用于检测呼出电话的状态。

首先,在清单文件中添加以下权限:

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

然后定义广播接收器(以下是示例代码!)

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;
        }

    }
} 

我将一些常量替换为它们的值,因为我看到许多不熟悉反射概念的人感到困惑(为了简化)。 警报基本上是接收器实际响铃时的状态!这不包括呼叫建立时间!


这不会跟踪呼出电话的响铃状态。回答不好。 - yams
@yams... 你为什么说它不能追踪呼出电话的状态?就像我之前提到的那样 - 它确实可以做到这一点。如果接收方正在响铃...它将在上述代码中触发第4种情况(ALERTING)。 - Ali Tariq

-1

我曾经遇到过类似的问题。我想要检测某些呼出电话的状态。最后我通过在Android中使用Visualizer类解决了问题。它可以返回当前扬声器播放音频的傅里叶变换。利用正在播放的音频类型(前扬声器上的小蜂鸣),您可以确定呼出电话的状态。例如,您可以知道电话接收器是否已经开始响铃。每当Visualizer返回非零样本时,就表示是某种状态。

背景音频不会干扰您,因为在通话期间,呼叫应用程序会关闭所有其他音频。

等待状态 off_hook,然后启动您的Visualizer类。


你好!你能提供一下你所做的样例来让我理解吗?这会非常有帮助。 - Edw590
请放置有用的答案代码,而非无用代码。 - yams

-3

试试这个,在else部分查看并进行更改,它会起作用的。

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();
                }
            }
        }
    }

1
如果(intent.getAction().equals(ACTION_IN))这行会在编译时出错。ACTION_IN是什么?能告诉我吗?谢谢。 - Ekanta Swain
私有静态最终字符串 ACTION_IN = "android.intent.action.PHONE_STATE"; 私有静态最终字符串 ACTION_OUT = "android.intent.action.NEW_OUTGOING_CALL"; - Pratik Dasa
1
在else部分,我们只能通过toast消息获取外拨号码。但是我如何获取外拨响铃状态呢?我在这里找不到。您能详细告诉我吗? - Ekanta Swain
Toast.makeText(context, "OUT : " + outCall, Toast.LENGTH_LONG).show(); 我只得到了这个提示。我怎么才能获取响铃状态,兄弟? - Ekanta Swain
没关系,Kancha,但你必须自己做一些事情,我不能为你完成整个项目。希望你能理解。 - Pratik Dasa
显示剩余3条评论

-3

试试这个,你可以使用继承自PhoneStateListener的PhoneListener。

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;

        }
    }
}

}


我已经尝试过了,但是对于外拨电话,我想要检查状态。在这段代码中,只有 OFFHOOK 和 IDLE 这两种状态适用于外拨电话。我需要 RINGING 状态。 - Ekanta Swain
外拨电话也会出现响铃状态 TelephonyManager.CALL_STATE_RINGING: - Murali Ganesan
1
我查看了你的代码,但是TelephonyManager.CALL_STATE_RINGING这一行从来没有被调用过。我需要添加额外的功能吗? - Ekanta Swain
你现在实际上获取了哪个状态? - Murali Ganesan
3
我收到 CALL_STATE_OFFHOOK 通知,但在电话被拒绝后我会收到 CALL_STATE_IDLE。但我从未收到 CALL_STATE_RINGING 通知。 - Ekanta Swain
1
这段代码有误!在使用广播接收器时,为什么要在其中使用监听器?onReceive方法将在状态发生改变时调用!当您在其中声明一个监听器时,在某些设备上它可能会被调用多次,并且会导致错误的结果,请尝试通过state = intent.getStringExtra(TelephonyManager.EXTRA_STATE);来提供广播的状态。 - Amir Hossein Ghasemi

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接