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

Flutter集成Agora应用Release模式下结束通话时崩溃求助

解决Flutter Release模式下结束Agora通话时崩溃的问题

看起来你碰到了Debug和Release模式行为不一致的典型问题,这种情况通常和Release模式的代码优化、上下文有效性或者资源清理顺序有关。结合你的代码和场景,我整理了几个可能的原因和对应的排查/修复方案:

1. 控制器中的context可能已失效

在控制器的callEndLog方法里,你直接使用了保存的context来显示对话框,但在Release模式下,Flutter的Widget树可能因为_onCallEnd里的setState更新,导致原context已经被dispose,此时使用它会触发崩溃。

修复方案:
把有效的context从_onCallEnd方法传递到后续流程,避免依赖控制器中可能失效的context:

// 修改_onCallEnd方法,传入context
Future<dynamic> _onCallEnd(BuildContext context) async {
  setState(() {
    isStopped = true;
    hostOnline = false;
  });
  await callEndLog(context); // 传递当前有效的context
}

// 修改控制器的callEndLog方法,接收context参数
callEndLog(BuildContext context) async{
  await videoCallRepo.callEndLog().then((value) {
    if(value != null){
      showDialog(
        barrierDismissible: false,
        context: context,
        builder: (BuildContext dialogContext) {
          return TerminateChatPopup(
            // 你的弹窗参数
          );
        },
      );
    }
  });
}

2. 异步操作的时序与Widget挂载状态问题

_onCallEnd里先执行setState再异步调用callEndLog,在Release模式下状态更新速度更快,可能导致对话框准备显示时,当前页面的Widget已经被弹出栈或处于不可用状态。

修复方案:
显示对话框前先检查当前State是否仍挂载:

if(value != null){
  // 确保当前页面Widget还未被dispose
  if (mounted) {
    showDialog(
      barrierDismissible: false,
      context: context,
      builder: (BuildContext dialogContext) {
        return TerminateChatPopup(
          // 你的弹窗参数
        );
      },
    );
  }
}

如果是在控制器中而非State类里,可以用Navigator.of(context).canPop()判断当前上下文是否有效,或者通过WidgetsBinding.instance.addPostFrameCallback确保UI状态稳定后再显示弹窗。

3. Release模式的代码混淆/优化问题

Flutter在Release模式下会开启代码压缩和优化,可能误优化了Agora SDK相关代码,或者导致变量/方法被错误移除,引发崩溃。

排查方案:
先临时关闭混淆测试,修改android/app/build.gradle:

buildTypes {
    release {
        minifyEnabled false
        shrinkResources false
        proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
    }
}

如果关闭后崩溃消失,说明是混淆规则问题,需要给Agora SDK添加官方文档中指定的混淆规则。

4. Agora资源未正确释放的冲突

结束通话时,Agora的RTC引擎资源可能还在清理中,此时显示弹窗可能引发线程冲突或资源占用问题。

修复方案:
在调用callEndLog前先正确释放Agora资源:

Future<dynamic> _onCallEnd(BuildContext context) async {
  // 先释放Agora RTC资源(具体方法参考Agora官方文档)
  await _rtcEngine.leaveChannel();
  await _rtcEngine.destroy();
  
  setState(() {
    isStopped = true;
    hostOnline = false;
  });
  await callEndLog(context);
}

5. 弹窗TerminateChatPopup的依赖数据问题

检查TerminateChatPopup是否使用了Release模式下可能为空的变量,比如从value中解析的通话时长等数据,是否因为JSON解析类型不匹配导致空指针。

排查方案:
在显示弹窗前打印或日志记录value的完整内容,确保传递给弹窗的参数都有效:

if(value != null){
  debugPrint('Call end log data: $value'); // 验证数据完整性
  if (mounted) {
    showDialog(
      // ...弹窗配置
    );
  }
}

额外建议

  • 捕获崩溃堆栈:在Release模式下,通过FlutterError.onError或崩溃收集工具获取具体崩溃信息,这是定位问题最直接的方式。
  • 逐步简化测试:先注释掉showDialog代码,确认Release模式下是否还崩溃,如果不崩溃,再逐步恢复弹窗代码,排查是弹窗本身还是显示时机的问题。

希望这些方案能帮你解决问题,如果有具体的崩溃堆栈信息,可以补充出来,能更精准地定位问题。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.11 07:48:54