Android - 如何检测或接收拨出电话?

时间:2014-10-04 06:28:34

标签: android broadcastreceiver phone-call telephony telephonymanager

有没有办法检测成功接听或接听拨出电话?我正在使用Intent.ACTION_CALL拨打电话,PhoneCallListener在拨出电话时找到通话状态,但我无法实现这一点。这可能在android?

3 个答案:

答案 0 :(得分:4)

在深入研究这个问题后,我得出了这个结论:

  1. PhoneStateListener不适用于拨出电话,它会调用OFFHOOK而不是RINGING,并且永远不会在ANSWER上调用OFFHOOK

    < / LI>
  2. 使用NotificationListenerService,您可以收听与拨出电话相关的已发布通知。你可以做类似下面的代码。这里的问题是我 无法从某些三星手机 获取通知文本,文本本身也可能会从一部手机变为另一部手机。 此外,它还需要API 18及以上

    public class NotificationListener extends NotificationListenerService {
    
        private String TAG = this.getClass().getSimpleName();
    
        @Override
        public void onNotificationPosted(StatusBarNotification sbn) {
            Log.i(TAG, "Notification Posted");
            Log.i(TAG, sbn.getPackageName() +
                    "\t" + sbn.getNotification().tickerText +
                    "\t" + sbn.getNotification().extras.getString(Notification.EXTRA_TEXT);
    
            Bundle extras = sbn.getNotification().extras;
    
            if ("Ongoing call".equals(extras.getString(Notification.EXTRA_TEXT))) {
                startService(new Intent(this, ZajilService.class).setAction(ZajilService.ACTION_CALL_ANSWERED));
            } else if ("Dialing".equals(extras.getString(Notification.EXTRA_TEXT))) {
                startService(new Intent(this, ZajilService.class).setAction(ZajilService.ACTION_CALL_DIALING));
            }
        }
    
        @Override
        public void onNotificationRemoved(StatusBarNotification sbn) {
            Log.i(TAG, "********** onNotificationRemoved");
            Log.i(TAG, "ID :" + sbn.getId() + "\t" + sbn.getNotification().tickerText + "\t" + sbn.getPackageName());
        }
    }
    
  3. 使用AccessibilityService,它比NotificationListenerService更基本,我认为所有API都支持它。但是也使用AccessibilityService, 某些电话在发出呼叫答复 时不会发布有用的事件。在大多数手机中,一旦呼叫应答,将提出一个事件,呼叫持续时间;它的打印输出如下:

  4. onAccessibilityEvent EventType: TYPE_WINDOW_CONTENT_CHANGED; EventTime: 21715433; PackageName: com.android.incallui; MovementGranularity: 0; Action: 0 [ ClassName: android.widget.TextView; Text: []; ContentDescription: 0 minutes 0 seconds;

    onAccessibilityEvent EventType: TYPE_WINDOW_CONTENT_CHANGED; EventTime: 21715533; PackageName: com.android.incallui; MovementGranularity: 0; Action: 0 [ ClassName: android.widget.TextView; Text: []; ContentDescription: 0 minutes 1 seconds;

    1. API 23有一个新类Call。它有更详细的通话状态; STATE_ACTIVE。你可以通过自己的用户界面替换手机的默认InCallUI InCallService我还没有尝试使用它,但无论如何,它仅限于API 23,Marshmallow。
    2. 作为结论,您需要构建一个与NotificationListenerAccessibilityService相结合的解决方案,以便涵盖所有手机,希望如此。

答案 1 :(得分:-1)

您需要使用RINGING状态和OFFHOOK状态的组合来确定呼叫是否已应答。

有关如何实现此目的的实际代码,请参阅此thread

答案 2 :(得分:-1)

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

我最近不得不在一个类似的项目上工作,我需要捕获拨出呼叫的振铃状态,我能找到的唯一方法是使用本机拨号应用程序的隐藏Api。这只适用于android&gt; 5.0因为api的变化。这是在Android 5.0.1上测试过的,并且像魅力一样。 (p.s.你需要一个有根设备才能工作,因为你需要将你的应用程序安装为系统应用程序(google how!),然后才能检测出局呼叫状态。)

对于记录,PhoneStateListener不能用于检测许多帖子中提到的传出呼叫状态。

首先,在清单文件

中添加此权限

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

然后定义你broadcastreceiver,(这是一个示例代码!)

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

    }
} 

我用它们的值替换了一些常量,因为我看到了不熟悉反射概念的人们之间的很多混淆(所以为了方便)。 警报基本上是接收器实际响铃时的状态!并且不包括呼叫建立时间,这意味着呼叫已成功接收!在precise_call_state类中还有其他选项(我没有探索过),以帮助您捕获正在接听的呼叫!