如何在用户挂断后通过代码移除TelecomManager发起的通话?
解决TelecomManager通话残留问题:结束通话后移除活跃通话记录
针对你遇到的Twilio通话应用中,结束通话后残留活跃通话、无法发起新通话的问题,以下是具体解决方案:
1. 基于ConnectionService管理通话生命周期
Android系统从API 26开始废弃了TelecomManager.endCall(),官方推荐通过ConnectionService来管理应用的通话生命周期,这也是Twilio Programmable Voice SDK依赖的核心组件。
在你自定义的Connection子类中,必须在通话结束时正确标记断开并销毁连接:
public class TwilioConnection extends Connection { // 处理系统触发的挂断 @Override public void onDisconnect() { setDisconnected(DisconnectCause.NORMAL); destroy(); // 关键:销毁连接,移除系统通话记录 } // 主动挂断通话的方法 public void terminateCall() { setDisconnected(DisconnectCause.LOCAL); destroy(); } }
在你的ConnectionService实现中,要确保每个通话结束时调用上述方法,不要只依赖Twilio的回调,必须同步更新系统通话状态。
2. 监听系统通话状态,主动清理残留
注册TelecomCallback监听系统通话状态,当系统进入空闲状态(CALL_STATE_IDLE)时,检查并清理本应用的残留通话:
TelecomManager telecomManager = getSystemService(TelecomManager.class); TelecomCallback telecomCallback = new TelecomCallback() { @Override public void onCallStateChanged(int state, String incomingNumber) { if (state == TelecomManager.CALL_STATE_IDLE) { // 获取本应用的所有活跃连接 List<Connection> activeConnections = getActiveConnections(); for (Connection conn : activeConnections) { // 验证是本应用的通话(可通过通话标识区分) if (conn.getExtras().getString("TWILIO_CALL_SID") != null) { conn.setDisconnected(DisconnectCause.NORMAL); conn.destroy(); } } } } }; // 注册回调,记得在页面销毁时注销 telecomManager.registerTelecomCallback(getMainExecutor(), telecomCallback);
3. 同步Twilio通话状态与系统状态
如果你使用Twilio Programmable Voice SDK,在通话断开的回调中,必须通知ConnectionService销毁对应连接:
Call twilioCall = ...; // 你的Twilio通话实例 twilioCall.setListener(new Call.Listener() { @Override public void onDisconnected(Call call, CallException error) { // 通过Call SID找到对应的Connection并销毁 for (Connection conn : getActiveConnections()) { if (call.getSid().equals(conn.getExtras().getString("TWILIO_CALL_SID"))) { conn.terminateCall(); break; } } } });
4. 发起新通话前的前置检查
在调用placeCall()发起新通话前,先检查当前是否有本应用的活跃通话,如有则优先清理:
public void initiateNewCall(Uri callUri) { TelecomManager telecomManager = getSystemService(TelecomManager.class); // 检查当前通话状态 if (telecomManager.getCallState() != TelecomManager.CALL_STATE_IDLE) { List<Call> activeCalls = telecomManager.getActiveCalls(); for (Call call : activeCalls) { // 确认是本应用发起的通话 if (call.getDetails().getPackageName().equals(getPackageName())) { // 通过ConnectionService结束该通话 yourConnectionService.endConnection(call.getDetails().getConnectionId()); } } } // 发起新通话 Bundle extras = new Bundle(); extras.putParcelable(TelecomManager.EXTRA_OUTGOING_CALL_EXTRAS, new Bundle()); telecomManager.placeCall(callUri, extras); }
内容的提问来源于stack exchange,提问作者Murad Eliyev
相关产品推荐
相关产品推荐

