Android拨出电话时无法检测到

为了检测何时应答出局呼叫,我尝试创build一个PhoneStateListener ,并从这个问题中侦听TelephonyManagerCALL_STATE_RINGINGCALL_STATE_OFFHOOKCALL_STATE_IDLE ,但似乎不起作用,如下所述。

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

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

然后,一个名为OutCallLoggerBroadcastReceiver在出现呼叫时捕获NEW_OUTGOING_CALL事件:

 <receiver android:name=".listener.OutCallLogger"> <intent-filter> <action android:name="android.intent.action.NEW_OUTGOING_CALL" /> </intent-filter> </receiver> 

接下来,我的OutCallLogger实现。 我设置了一个名为noCallListenerYet的布尔值,以避免在调用onReceive()时将新的PhoneStateListenerTelephonyManager

 public class OutCallLogger extends BroadcastReceiver { private static boolean noCallListenerYet = true; @Override public void onReceive(final Context context, Intent intent) { number = intent.getStringExtra(Intent.EXTRA_PHONE_NUMBER); if (noCallListenerYet) { final TelephonyManager tm = (TelephonyManager) context.getSystemService( Context.TELEPHONY_SERVICE); 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); noCallListenerYet = false; } } } 

现在,当我在我的设备中拨打电话时, CALL_STATE_RINGING 从不被调用。 当其他线路开始响铃时,我总是只打印“IDLE”到“OFFHOOK”,当呼叫被应答时,什么都没有,打电话结束时打印输出“IDLE”。

我怎样才能可靠地检测到一个传出的电话在Android应答时,或甚至可能?

由于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中find所有可能的调用状态,以及意图在TelephonyRegistry.java中包含的所有附加信息。

它看起来像RINGING状态只能通过来电。 传出呼叫从IDLE更改为OFFHOOK,因此查看电话状态可能无法实现此目的。

我认为可以使用内部函数,看看这个: Android电话堆栈中不同的Call状态代表什么?

也许尝试使用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文件中find了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 } 

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

请注意:

 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”参数吗? 是的,该代码只能检测您的电话呼叫状态时,有一个来电到您的设备。

你可以做以下…不是很精确,但可以做的伎俩:

  1. 您使用接收器进行android.intent.action.NEW_OUTGOING_CALL操作
  2. 当接收者被调用时,你在某处(例如一个静态variables)存储NEW_OUTGOIN_CALL状态,并在发生这种情况时以毫秒为单位(即new 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); } 

在CALL_STATE_OFFHOOK的情况下,你检查最后存储的状态是NEW_OUTGOING_CALL,并且不超过aprox。 自上次状态变更以来,已经过了10秒。 这意味着电话最多在10秒前发起一个呼叫,现在他处于摘机状态(意思是主动呼叫),而不经过空闲或振铃。 这可能意味着电话被回答了。

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

我之前在这个项目中也尝试了这个东西,我遇到了同样的问题,然后我就像下面这样解决了。 我花了三个class,如下所示。

  1. AutoCallReceiver:使用PhoneStateListener.LISTEN_CALL_STATE注册TelephonyManager

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

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"/>