在Android中无法检测到何时应答拨出呼叫

时间:2012-10-30 07:17:25

标签: android broadcastreceiver

为了检测何时接听拨出电话,我尝试创建PhoneStateListener并收听TelephonyManager的{​​{1}},CALL_STATE_RINGINGCALL_STATE_OFFHOOK,来自this question,但它似乎不起作用,如下所述。

首先,我在清单中注册了以下权限:

CALL_STATE_IDLE

然后,一个名为<uses-permission android:name="android.permission.PROCESS_OUTGOING_CALLS" /> 的{​​{1}}会在拨打电话时捕获BroadcastReceiver事件:

OutCallLogger

接下来,我执行NEW_OUTGOING_CALL。我设置了一个名为<receiver android:name=".listener.OutCallLogger"> <intent-filter> <action android:name="android.intent.action.NEW_OUTGOING_CALL" /> </intent-filter> </receiver> 的布尔值,以避免在调用OutCallLogger时将noCallListenerYet附加到PhoneStateListener

TelephonyManager

现在,当我在设备中拨打电话时,onReceive() 永远不会被调用。当另一条线路开始响铃时,我总是只能将“IDLE”打印输出到“OFFHOOK” ,当电话接听时没有任何内容,并且在通话结束时再次打印输出“IDLE”。

如何可靠地检测何时在Android中应答拨出电话,或者甚至是可能的?

6 个答案:

答案 0 :(得分:11)

从Android 5.0开始,这可用于系统应用程序。但您需要使用隐藏的Android API。

我让它像这样工作:

<uses-permission android:name="android.permission.READ_PRECISE_PHONE_STATE" />
<receiver android:name=".listener.OutCallLogger">
    <intent-filter>
        <action android:name="android.intent.action.PRECISE_CALL_STATE" />
    </intent-filter>
</receiver>
public class OutCallLogger extends BroadcastReceiver {

    @Override
    public void onReceive(Context context, Intent intent) {
        switch (intent.getIntExtra(TelephonyManager.EXTRA_FOREGROUND_CALL_STATE, -2) {
            case PreciseCallState.PRECISE_CALL_STATE_IDLE:
                Log.d(This.LOG_TAG, "IDLE");
                break;
            case PreciseCallState.PRECISE_CALL_STATE_DIALING:
                Log.d(This.LOG_TAG, "DIALING");
                break;
            case PreciseCallState.PRECISE_CALL_STATE_ALERTING:
                Log.d(This.LOG_TAG, "ALERTING");
                break;
            case PreciseCallState.PRECISE_CALL_STATE_ACTIVE:
                Log.d(This.LOG_TAG, "ACTIVE");
                break;
        }
    }
}

您可以在PreciseCallState.java中找到所有可能的通话状态,并在TelephonyRegistry.java中找到意图包含的所有额外内容。

答案 1 :(得分:3)

看起来只有来电才能达到RINGING状态。拨出电话从IDLE变为OFFHOOK,因此查看电话状态可能无法实现此目的。

我认为可以使用内部函数,看看:What does the different Call states in the Android telephony stack represent?

答案 2 :(得分:1)

也许尝试使用CallManager?查看http://grepcode.com/file/repository.grepcode.com/java/ext/com.google.android/android/2.3.3_r1/com/android/internal/telephony/CallManager.java。我还在我的计算机上的SDK文件中找到了CallManager.java。链接页面中的以下文字似乎很有希望:

Register for getting notifications for change in the Call State Call.State This is 
called PreciseCallState because the call state is more precise than the Phone.State 
which can be obtained using the android.telephony.PhoneStateListener Resulting events 
will have an AsyncResult in Message.obj. AsyncResult.userData will be set to the obj 
argument here. The h parameter is held only by a weak reference.

1051
1052    public void registerForPreciseCallStateChanged(Handler h, int what, Object obj){
1053        mPreciseCallStateRegistrants.addUnique(h, what, obj);
1054    }

我没有尝试过任何代码,所以真的不知道它是否可以做你想要的,但我很想知道。

答案 3 :(得分:1)

请注意:

tm.listen(new PhoneStateListener() {
            @Override
            public void onCallStateChanged(int state, String incomingNumber) {
                switch (state) {
                    case TelephonyManager.CALL_STATE_RINGING:
                        Log.d(This.LOG_TAG, "RINGING");
                        break;
                    case TelephonyManager.CALL_STATE_OFFHOOK:
                        Log.d(This.LOG_TAG, "OFFHOOK");
                        break;
                    case TelephonyManager.CALL_STATE_IDLE:
                        Log.d(This.LOG_TAG, "IDLE");
                        break;
                    default:
                        Log.d(This.LOG_TAG, "Default: " + state);
                        break;
                }
            }
        }, PhoneStateListener.LISTEN_CALL_STATE);

您是否看到“incomingNumber”参数?是的,只有当您的设备有来电时,该代码才能检测到您的电话呼叫状态。

答案 4 :(得分:-1)

你可以做以下......不是很精确但可以做到这一点:

  1. 您将接收器用于 android.intent.action.NEW_OUTGOING_CALL 操作
  2. 当调用接收器时,你将某个地方(例如静态变量)存储在NEW_OUTGOIN_CALL状态和发生这种情况的时间(即新的Date()。getTime())
  3. 您使用另一个接收器 android.intent.action.PHONE_STATE ,并在onReceive中执行以下操作:

    if (intent.getAction().equals("android.intent.action.PHONE_STATE")) {
        TelephonyManager telephony = (TelephonyManager) context.getSystemService(Context.TELEPHONY_SERVICE);
        telephony.listen(new PhoneStateListener() {
            public void onCallStateChanged(int state, String incomingNumber) {
                  switch(state) {
                    case TelephonyManager.CALL_STATE_IDLE:
                    break;
                    case TelephonyManager.CALL_STATE_OFFHOOK:
                    break;
                    case TelephonyManager.CALL_STATE_RINGING:
                    break;
                   }
            } 
        }, PhoneStateListener.LISTEN_CALL_STATE);
    
    }
    
  4. 在CALL_STATE_OFFHOOK案例中,您检查最后存储的状态是否为NEW_OUTGOING_CALL,并且不会超过aprox。自上次状态改变以来已过去10秒。这意味着手机最多10秒前发起了一次通话,而现在他处于摘机状态(意味着有效通话)而没有通过空闲或振铃。这可能意味着电话已经接听了。

答案 5 :(得分:-2)

这里你的答案是你在OutGoingCallReceiver中实现了CallStateListener,这是错误的。您必须在PhoneStateListener

中实现CallStateListener

我在早期的项目中也试过这个东西,我遇到了同样的问题,然后我解决了它,如下所示。我参加了3节课。

  1. AutoCallReceiver:使用PhoneStateListener.LISTEN_CALL_STATE

  2. 注册TelephonyManager
  3. CallStateListener侦听三个状态为TelephonyManager.CALL_STATE_IDLETelephonyManager.CALL_STATE_OFFHOOKTelephonyManager.CALL_STATE_RINGING

  4. 3.OutGoingCallReceiver处理呼叫

    public class OutGoingCallReceiver extends BroadcastReceiver {  
    
        /* onReceive will execute on out going call */
        @Override  
        public void onReceive(Context context, Intent intent) {  
    
             Toast.makeText(context, "OutGoingCallReceiver", Toast.LENGTH_SHORT).show();
    
        }  
      } 
    

    public class CallStateListener extends PhoneStateListener {  
    
        String number=""; // variable for storing incoming/outgoing number
        Context mContext; // Application Context
    
    
        //Constructor that will accept Application context as argument
        public CallStateListener(Context context) {
            mContext=context;
        }
    
        // This function will automatically invoke when call state changed
        public void onCallStateChanged(int state,String incomingNumber)
        {  
               boolean end_call_state=false; // this variable when true indicate that call is disconnected
               switch(state)
                   {  
                     case TelephonyManager.CALL_STATE_IDLE:  
                           // Handling Call disconnect state after incoming/outgoing call 
                         Toast.makeText(mContext, "idle", Toast.LENGTH_SHORT).show();
    
    
                      break;  
    
                     case TelephonyManager.CALL_STATE_OFFHOOK:     
                         // Handling outgoing call  
                         Toast.makeText(mContext, "OFFHOOK", Toast.LENGTH_SHORT).show();
                          // saving outgoing call state so that after disconnect idle state can act accordingly
    
    
                      break;  
                     case TelephonyManager.CALL_STATE_RINGING: 
                         Toast.makeText(mContext, "RINGING", Toast.LENGTH_SHORT).show();
    
                      break;  
    
                   }  
    
    
        }   
    
      } 
    

    public class AutoCallReceiver extends BroadcastReceiver {  
    
    
       /* onReceive will execute on call state change */
        @Override  
        public void onReceive(Context context, Intent intent) { 
    
            // Instantiating PhoneStateListener
            CallStateListener phoneListener=new CallStateListener(context);  
    
            // Instantiating TelephonyManager
          TelephonyManager telephony = (TelephonyManager)   
                   context.getSystemService(Context.TELEPHONY_SERVICE);  
    
            // Registering the telephony to listen CALL STATE change
          telephony.listen(phoneListener,PhoneStateListener.LISTEN_CALL_STATE);  
        }  
    

    }

     <receiver android:name=".OutGoingCallReceiver">
        <intent-filter>
          <action android:name="android.intent.action.NEW_OUTGOING_CALL" />
        </intent-filter>
    </receiver>
     <receiver android:name=".AutoCallReceiver">
                <intent-filter>
                         <action android:name="android.intent.action.PHONE_STATE" />
                </intent-filter>
             </receiver>
        </application>
     <uses-permission android:name="android.permission.PROCESS_OUTGOING_CALLS"/>