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

Xamarin Android原生SipManager注销仅断点生效问题求助

解决Xamarin Android SIP注销时服务器收不到消息的问题

哥们,我之前碰到过几乎一模一样的异步时序问题,你这个断点能正常工作、无断点就失败的情况,核心原因大概率是注销请求还没来得及发送到服务器,后续的页面跳转、资源释放操作就把SIP相关的线程/连接给中断了,加上DATA_CONNECTION_LOST错误,也印证了连接被提前切断的问题。给你几个具体的解决方案:

1. 等待注销操作确认完成,再执行后续逻辑

Xamarin的SipManager.Unregister是异步操作,你现在直接调用后立刻执行Close和资源释放,相当于没给它发请求的时间。可以通过注册监听回调,等服务器确认注销成功后再处理后续:

修改CloseLocalProfile方法,添加注销回调

public void CloseLocalProfile(Action onLogoutCompleted) {
    if (MainActivity.mSipManager == null) {
        onLogoutCompleted?.Invoke();
        return;
    }
    try {
        if (MainActivity.mSipProfile != null) {
            Log.Info("Unregistering profile", "Un registering profile ");
            // 注册注销监听,等待服务器确认
            MainActivity.mSipManager.Unregister(MainActivity.mSipProfile, new SipRegistrationListener(onLogoutCompleted));
        } else {
            onLogoutCompleted?.Invoke();
        }
    } catch (Exception ee) {
        Log.Debug("onDestroy", "Failed to close local profile.", ee.Message);
        onLogoutCompleted?.Invoke();
    }
}

// 实现SIP注销监听类
private class SipRegistrationListener : Java.Lang.Object, ISipRegistrationListener {
    private readonly Action _onCompleted;

    public SipRegistrationListener(Action onCompleted) {
        _onCompleted = onCompleted;
    }

    public void OnRegistrationDone(string localProfileUri, long expiryTime) {
        Log.Info("Logout", "Registration unconfirmed successfully");
        // 注销成功后,再执行关闭Profile和资源释放
        try {
            Log.Info("Closing profile", "Closing current profile ");
            MainActivity.mSipManager.Close(MainActivity.mSipProfile.UriString);
            MainActivity.mSipManager.UnregisterFromRuntime();
            MainActivity.mSipProfile.UnregisterFromRuntime();
            MainActivity.mSipManager = null;
            MainActivity.mSipProfile = null;
        } catch (Exception ex) {
            Log.Debug("Logout", "Failed to clean up resources", ex.Message);
        } finally {
            _onCompleted?.Invoke();
        }
    }

    public void OnRegistrationFailed(string localProfileUri, int errorCode, string errorMessage) {
        Log.Error("Logout", $"Registration un failed: {errorCode} - {errorMessage}");
        // 即使注销失败,也要执行后续清理和回调
        try {
            MainActivity.mSipManager.Close(MainActivity.mSipProfile.UriString);
            MainActivity.mSipManager.UnregisterFromRuntime();
            MainActivity.mSipProfile.UnregisterFromRuntime();
            MainActivity.mSipManager = null;
            MainActivity.mSipProfile = null;
        } catch (Exception ex) {
            Log.Debug("Logout", "Failed to clean up resources after failure", ex.Message);
        } finally {
            _onCompleted?.Invoke();
        }
    }

    public void OnRegistrationTimeout(string localProfileUri) {
        Log.Warn("Logout", "Registration un timeout");
        _onCompleted?.Invoke();
    }
}

2. 调整DoLogout方法,等待注销完成再跳转

原来的DoLogout里直接调用CloseLocalProfile就跳转,现在要等注销回调完成后再执行导航:

private async Task DoLogout() {
    var tcs = new TaskCompletionSource<bool>();
    _sipPlatformManager.CloseLocalProfile(() => {
        tcs.SetResult(true);
    });
    // 等待注销操作完成
    await tcs.Task;
    // RESET user information
    await _navigationService.NavigateAsync("Login");
}

3. 排查DATA_CONNECTION_LOST的关联问题

这个错误通常是因为SIP连接在注销过程中被意外中断,上面的修改已经确保了注销请求完成后再释放资源,大概率能解决这个问题。如果还是出现,可以检查:

  • 注销时的网络状态,确保网络稳定
  • 是否有其他地方在注销过程中修改了网络连接或者SIP相关的权限

核心思路总结

本质就是异步操作的时序问题:断点给了异步请求足够的执行时间,无断点时后续操作(页面跳转、资源释放)抢占了线程,导致注销消息没发出去。通过监听回调+等待完成的方式,就能保证注销请求被服务器接收后再执行后续逻辑。

内容的提问来源于stack exchange,提问作者Greta

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.28 09:43:58