我需要在铃声结束后结束通话(有点像未接来电)。我使用BroadcastReceiver
和PhoneStateListener
来监控状态。
问题是我正在接收广播以及phonenumber
,并且听众工作得很好 - 它进入switch
并执行case
预期,但它没有' t执行endCall
接口的ITelephony
方法。这是我的代码:
清单:
<uses-permission android:name="android.permission.CALL_PHONE" />
<uses-permission android:name="android.permission.READ_PHONE_STATE" />
<uses-permission android:name="android.permission.MODIFY_PHONE_STATE"
tools:ignore="ProtectedPermissions" />
<uses-permission android:name="android.permission.PROCESS_OUTGOING_CALLS"/>
<uses-permission android:name="android.permission.READ_CALL_LOG" />
<uses-permission android:name="android.permission.WRITE_CALL_LOG" />
<receiver
android:name=".EndCall"
android:enabled="true" >
<intent-filter>
<action android:name="android.intent.action.NEW_OUTGOING_CALL" />
</intent-filter>
</receiver>
EndCall.java
public class EndCall extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
Log.i("Debug", "Received a broadcast...");
String phonenumber = intent.getStringExtra(Intent.EXTRA_PHONE_NUMBER);
Log.i("Debug", "Phone number: " + phonenumber);
TelephonyManager tm = (TelephonyManager) context.getSystemService(Context.TELEPHONY_SERVICE);
EndCallListener callListener = new EndCallListener(context, tm);
tm.listen(callListener, PhoneStateListener.LISTEN_CALL_STATE);
}
}
EndCallListener.java:
public class EndCallListener extends PhoneStateListener {
Context context;
TelephonyManager tm;
public EndCallListener(Context context, TelephonyManager tm) {
this.context = context;
this.tm = tm;
}
@Override
public void onCallStateChanged(int state, String incomingNumber) {
switch (state) {
case TelephonyManager.CALL_STATE_OFFHOOK:
Log.i("Debug", "OFFHOOK");
try {
Log.i("Debug", "Inside try...");
Class c = Class.forName(tm.getClass().getName());
Method m = c.getDeclaredMethod("getITelephony");
ITelephony telephonyService = (ITelephony) m.invoke(tm);
//nothing happens after this...
if(telephonyService.endCall()) {
Log.i("Debug", "Call ended...");
} else {
Log.i("Debug", "Call not ended...");
}
} catch (ClassNotFoundException e) {
e.printStackTrace();
} catch (NoSuchMethodException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (RemoteException e) {
e.printStackTrace();
}
break;
case TelephonyManager.CALL_STATE_IDLE:
Log.i("Debug", "IDLE");
break;
}
}
}
ITelephony.aidl
package com.android.internal.telephony;
interface ITelephony {
boolean endCall();
void answerRingingCall();
void silenceRinger();
}
答案 0 :(得分:1)
最后一条评论让事情不清楚(在问题帖子中)..“它确实结束了通话,但问题是我想在通话时或者通话结束后的一段时间结束通话。”< / p>
所以通话已经结束,但你希望它在响铃时或一段时间后结束? 这里有2个案例: - 响铃时:您需要检查CALL_STATE_RINGING然后转到How to reject a call programatically android并检查那里的技术
我可能不合时宜,我建议你澄清你的评论/问题
答案 1 :(得分:1)
您仅监控清单中的拨出电话。您还可以在清单接收器中监控电话状态。
基本上你想在几声(例如10秒)响铃或被拣选后结束外拨电话。
由于Android没有发送任何更新,因此没有任何方式可以知道外出呼叫是否已收到回复或仍然响铃。
但是,因为,你需要在几秒钟之后结束传出呼叫,你的EndCallListener代码应该是这样的: -
public class EndCallListener extends PhoneStateListener {
Context context;
TelephonyManager tm;
public EndCallListener(Context context, TelephonyManager tm) {
this.context = context;
this.tm = tm;
}
@Override
public void onCallStateChanged(int state, String incomingNumber) {
switch (state) {
case TelephonyManager.CALL_STATE_OFFHOOK:
handler.postDelayed(new Runnable() {
@Override
public void run() {
Log.i("Debug", "OFFHOOK");
try {
Log.i("Debug", "Inside try...");
Class c = Class.forName(tm.getClass().getName());
Method m = c.getDeclaredMethod("getITelephony");
ITelephony telephonyService = (ITelephony) m.invoke(tm);
//nothing happens after this...
if(telephonyService.endCall()) {
Log.i("Debug", "Call ended...");
} else {
Log.i("Debug", "Call not ended...");
}
} catch (ClassNotFoundException e) {
e.printStackTrace();
} catch (NoSuchMethodException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (RemoteException e) {
e.printStackTrace();
}
}
}, 10000);
break;
case TelephonyManager.CALL_STATE_IDLE:
Log.i("Debug", "IDLE");
break;
}
}
}
答案 2 :(得分:1)
您只能检测到电话何时开始拨打电话以及何时拨打电话,但您无法确定何时拨打电话&#34;开始了。
唯一的解决方法是在拨出电话开始后挂断并通过几秒钟,但是,您再也不能保证手机会响铃:
public class EndCallListener extends PhoneStateListener {
int lastState = TelephonyManager.CALL_STATE_IDLE;
boolean isIncoming;
//Incoming call- IDLE to RINGING when it rings, to OFFHOOK when it's answered, to IDLE when hung up
//Outgoing call- from IDLE to OFFHOOK when dialed out, to IDLE when hunged up
@Override
public void onCallStateChanged(int state, String incomingNumber) {
super.onCallStateChanged(state, incomingNumber);
if(lastState == state){
//No change
return;
}
switch (state) {
case TelephonyManager.CALL_STATE_RINGING:
isIncoming = true;
//incoming call started
break;
case TelephonyManager.CALL_STATE_OFFHOOK:
//Transition of ringing->offhook are pickups of incoming calls. Nothing down on them
if(lastState != TelephonyManager.CALL_STATE_RINGING){
isIncoming = false;
//outgoing call started
new Handler().postDelayed(new Runnable() {
@Override
public void run() {
Log.i("Debug", "OFFHOOK");
try {
Log.i("Debug", "Inside try...");
Class c = Class.forName(tm.getClass().getName());
Method m = c.getDeclaredMethod("getITelephony");
ITelephony telephonyService = (ITelephony) m.invoke(tm);
//nothing happens after this...
if(telephonyService.endCall()) {
Log.i("Debug", "Call ended...");
} else {
Log.i("Debug", "Call not ended...");
}
} catch (ClassNotFoundException e) {
e.printStackTrace();
} catch (NoSuchMethodException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (RemoteException e) {
e.printStackTrace();
}
}
}, 10000);
}
break;
case TelephonyManager.CALL_STATE_IDLE:
//End of call(Idle). The type depends on the previous state(s)
if(lastState == TelephonyManager.CALL_STATE_RINGING){
// missed call
}
else if(isIncoming){
//incoming call ended
}
else{
//outgoing call ended
}
break;
}
lastState = state;
}
}
}