You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在用户挂断后通过代码移除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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.24 23:52:47