24

当电话响起时,我设法准备了一项活动。现在我需要知道如何取消此活动,当我接听电话或拒接电话时。我打电话EXTRA_STATE_IDLE还是EXTRA_STATE_OFFHOOK

有任何想法吗?

显现

    <receiver android:name=".IncomingBroadcastReceiver">
        <intent-filter>
            <action android:name="android.intent.action.PHONE_STATE" />
        </intent-filter>
    </receiver>

IncomingBroadcastReceiver java 类

public class IncomingBroadcastReceiver extends BroadcastReceiver {
    @Override
    public void onReceive(Context context, Intent intent) {
        String state = intent.getStringExtra(TelephonyManager.EXTRA_STATE);
        // If an incoming call arrives
        if (state.equals(TelephonyManager.EXTRA_STATE_RINGING)) { //Did my work }
4

6 回答 6

27

如果是拨出电话,上述答案是完全错误的。在 Android 中,无法检测到呼叫是否实际得到应答(在拨出电话的情况下)。在您拨打号码的那一刻,该off_hook状态被触发。这是Android编程的缺点之一。

于 2014-02-16T13:18:03.917 回答
22

在您的 onReceive 中:

PhoneStateChangeListener pscl = new PhoneStateChangeListener();
TelephonyManager tm = (TelephonyManager)this.getSystemService(Context.TELEPHONY_SERVICE);
tm.listen(pscl, PhoneStateListener.LISTEN_CALL_STATE);

单独的类:

private class PhoneStateChangeListener extends PhoneStateListener {
    public static boolean wasRinging;
    String LOG_TAG = "PhoneListener";
    @Override
    public void onCallStateChanged(int state, String incomingNumber) {
        switch(state){
            case TelephonyManager.CALL_STATE_RINGING:
                 Log.i(LOG_TAG, "RINGING");
                 wasRinging = true;
                 break;
            case TelephonyManager.CALL_STATE_OFFHOOK:
                 Log.i(LOG_TAG, "OFFHOOK");

                 if (!wasRinging) {
                     // Start your new activity
                 } else {
                     // Cancel your old activity
                 }

                 // this should be the last piece of code before the break
                 wasRinging = true;
                 break;
            case TelephonyManager.CALL_STATE_IDLE:
                 Log.i(LOG_TAG, "IDLE");
                 // this should be the last piece of code before the break
                 wasRinging = false;
                 break;
        }
    }
}

您需要做的就是编写一些代码来检查之前的状态是否为“响铃”。如果当前状态是空闲并且之前的状态是响铃,他们就取消了通话。如果当前状态是摘机而之前的状态是振铃,他们会接听电话。

于 2012-03-13T13:51:43.567 回答
7

以下是它在不同场景中经历的状态:

1) 接听来电

CALL_STATE_RINGING => CALL_STATE_OFFHOOK (After Answering call) => CALL_STATE_IDLE (After End call) 

2)拒绝/不接听(未接)接听电话

CALL_STATE_RINGING => CALL_STATE_IDLE (After End call)  

3) 拨打电话

CALL_STATE_OFFHOOK (After dialing) => CALL_STATE_IDLE (After End call) 

代码

  int prev_state=0;


  public class CustomPhoneStateListener extends PhoneStateListener {  

        private static final String TAG = "CustomPhoneStateListener";  

        @Override  
        public void onCallStateChanged(int state, String incomingNumber){  

            if(incomingNumber!=null&&incomingNumber.length()>0) incoming_nr=incomingNumber;   

            switch(state){  
                case TelephonyManager.CALL_STATE_RINGING:  
                        Log.d(TAG, "CALL_STATE_RINGING");  
                        prev_state=state;  
                        break;  
                case TelephonyManager.CALL_STATE_OFFHOOK:  
                Log.d(TAG, "CALL_STATE_OFFHOOK");  
                prev_state=state;  
                break;  
                case TelephonyManager.CALL_STATE_IDLE:  
                    Log.d(TAG, "CALL_STATE_IDLE==>"+incoming_nr);  
                    NumberDatabase database=new NumberDatabase(mContext);  
                    if((prev_state==TelephonyManager.CALL_STATE_OFFHOOK)){  
                        prev_state=state;  
                        //Answered Call which is ended  
                    }  
                    if((prev_state==TelephonyManager.CALL_STATE_RINGING)){  
                        prev_state=state;  
                        //Rejected or Missed call  
                    }  
                    break;  

            }  
        }  
    }  

在您的接收器中

onReceive(Context context, Intent intent) {  
        TelephonyManager telephony = (TelephonyManager)context.getSystemService(Context.TELEPHONY_SERVICE); //TelephonyManager object  
        CustomPhoneStateListener customPhoneListener = new CustomPhoneStateListener();  
        telephony.listen(customPhoneListener, PhoneStateListener.LISTEN_CALL_STATE);          //Register our listener with TelephonyManager  

        Bundle bundle = intent.getExtras();  
        String phoneNr= bundle.getString("incoming_number");  

        mContext=context;  
 }  
于 2012-03-13T13:41:13.937 回答
2

下面是通过可访问性事件检测拨出电话的代码 -

AccessibilityService添加一个在您的项目中扩展的类-

public class CallDetection extends AccessibilityService {
@Override
public void onAccessibilityEvent(AccessibilityEvent event) {
     acquireLock(this);
    Log.d("myaccess","after lock");
    if (event.getEventType() == AccessibilityEvent.TYPE_WINDOW_CONTENT_CHANGED) {
        Log.d("myaccess","in window changed");
        AccessibilityNodeInfo info = event.getSource();
        if (info != null && info.getText() != null) {
            String duration = info.getText().toString();
            String zeroSeconds = String.format("%02d:%02d", new Object[]{Integer.valueOf(0), Integer.valueOf(0)});
            String firstSecond = String.format("%02d:%02d", new Object[]{Integer.valueOf(0), Integer.valueOf(1)});
            Log.d("myaccess","after calculation - "+ zeroSeconds + " --- "+ firstSecond + " --- " + duration);
            if (zeroSeconds.equals(duration) || firstSecond.equals(duration)) {
                Toast.makeText(getApplicationContext(),"Call answered",Toast.LENGTH_SHORT).show();
               // Your Code goes here
            }
            info.recycle();
        }
    }
}


@Override
protected void onServiceConnected() {
    super.onServiceConnected();
    Toast.makeText(this,"Service connected",Toast.LENGTH_SHORT).show();
    AccessibilityServiceInfo info = new AccessibilityServiceInfo();
    info.eventTypes = AccessibilityEvent.TYPE_WINDOW_CONTENT_CHANGED;
    info.feedbackType = AccessibilityServiceInfo.FEEDBACK_GENERIC;
    info.notificationTimeout = 0;
    info.packageNames = null;
    setServiceInfo(info);
}

@Override
public void onInterrupt() {

}
}

但是要使功能event.getSource()正常工作,您必须通过 xml 指定一些服务配置,因此在您的项目中创建一个xml文件夹并添加一个名为 serviceconfig.xml的 xml 文件(您可以给任何您想要的名称。

serviceconfig 的内容如下 -

<accessibility-service xmlns:android="http://schemas.android.com/apk/res/android"
android:description="@string/callDetection"
android:accessibilityEventTypes="typeWindowContentChanged"
android:notificationTimeout="100"
android:canRetrieveWindowContent="true"
/>

您可以在此处找到有关serviceconfig的更多信息

现在将您的服务添加到您的清单文件中,如下所示 -

<service android:name=".CallDetection"
        android:permission="android.permission.BIND_ACCESSIBILITY_SERVICE"
        android:label="@string/callDetection">
        <intent-filter>
            <action android:name="android.accessibilityservice.AccessibilityService" />
        </intent-filter>
        <meta-data
            android:name="android.accessibilityservice"
            android:resource="@xml/serviceconfig" />
</service>

大功告成,只需运行应用程序并转到手机中的辅助功能设置,您将找到一个名为检测的选项(或您作为服务描述提供的任何名称),将其打开以授予您应用程序的辅助功能权限。

现在,当您接听电话时,您会看到祝酒词。

您可以在其中编写任何您想要的代码,也可以在活动中调用回调函数

最重要的是- 在接听电话之前不要拨打您的通话窗口(android 拨号器窗口),否则这将不起作用。

注意- 由于 android 没有提供任何解决方案来检测呼叫是否被应答,这是我所做的最好的选择,希望它对你有用。

于 2017-07-11T21:44:49.797 回答
0
//
public class myService extends InCallService 
{
    // Here... :)
    @Override public void onCanAddCallChanged(boolean canAddCall) 
    {
        super.onCanAddCallChanged(canAddCall);  
    }
}
于 2020-07-24T06:49:05.257 回答
0

要检测是否接到电话,您可以检测“你好”的声音。“你好”语音是呼叫进度频率之外的频率(语音活动)。作为参考,您可以查看此数据表部分:https ://www.cmlmicro.com/products/call-progress-and-voice-detector/

于 2021-06-13T18:43:38.117 回答