为了检测何时接听拨出电话,我尝试创建PhoneStateListener
并收听TelephonyManager
的{{1}},CALL_STATE_RINGING
和CALL_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中应答拨出电话,或者甚至是可能的?
答案 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)
你可以做以下......不是很精确但可以做到这一点:
您使用另一个接收器 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秒前发起了一次通话,而现在他处于摘机状态(意味着有效通话)而没有通过空闲或振铃。这可能意味着电话已经接听了。
答案 5 :(得分:-2)
这里你的答案是你在OutGoingCallReceiver中实现了CallStateListener,这是错误的。您必须在PhoneStateListener
中实现CallStateListener我在早期的项目中也试过这个东西,我遇到了同样的问题,然后我解决了它,如下所示。我参加了3节课。
AutoCallReceiver:使用PhoneStateListener.LISTEN_CALL_STATE
CallStateListener侦听三个状态为TelephonyManager.CALL_STATE_IDLE
,TelephonyManager.CALL_STATE_OFFHOOK
,TelephonyManager.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"/>