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

Noo*_*ani 5 android telephony phone-call broadcastreceiver telephonymanager

有什么办法可以检测到拨出电话是否成功接听或接听?我Intent.ACTION_CALL用于拨打电话并PhoneCallListener在拨出电话接听时查找通话状态,但我无法实现这一目标。这在android中可能吗?

小智 6

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

  1. PhoneStateListener不适用于拨出电话,它调用OFFHOOK而不是调用 ANSWERRINGING并且OFFHOOK从不调用它。

  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());
        }
    }
    
    Run Code Online (Sandbox Code Playgroud)
  3. 使用AccessibilityService,它比NotificationListenerService我认为所有 API 都支持它更基本。但是也使用 AccessibilityService,有些手机在调用 Answer 的情况下不会发布有用的事件。在大多数电话中,一旦呼叫接听就会引发一个事件,并带有通话持续时间;它的打印输出如下所示:

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. 您可以通过InCallService用您自己的 UI 替换手机的默认 InCallUI我还没有尝试使用它,但无论如何,它仅限于 API 23,棉花糖。

作为结论,您需要构建一个结合NotificationListener和的解决方案AccessibilityService,以覆盖所有电话,希望如此。