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

Flutter集成Agora SDK(v6.3.0)遇动态库加载及空检查异常

Flutter集成Agora RTC Engine(v6.3.0)两类错误及解决方案

问题描述

使用agora_rtc_engine: ^6.3.0开发Flutter实时音视频功能时,出现两类错误:

1. 动态库加载失败

Invalid argument(s): Failed to load dynamic library 'libiris_method_channel.so': dlopen failed: library "libiris_method_channel.so" not found
E/flutter ( 3573): #0 _open (dart:ffi-patch/ffi_dynamic_library_patch.dart:11:43)
E/flutter ( 3573): #1 new DynamicLibrary.open (dart:ffi-patch/ffi_dynamic_library_patch.dart:22:12)
E/flutter ( 3573): #2 _loadLib (package:iris_method_channel/src/platform/io/iris_event_io.dart:16:31)
E/flutter ( 3573): #3 new IrisEventIO (package:iris_method_channel/src/platform/io/iris_event_io.dart:26:54)
E/flutter ( 3573): #4 IrisMethodChannelInternalIO._execute (package:iris_method_channel/src/platform/io/iris_method_channel_internal_io.dart:421:64)
E/flutter ( 3573): #5 _delayEntrypointInvocation. (dart:isolate-patch/isolate_patch.dart:300:17)
E/flutter ( 3573): #6 _RawReceivePort._handleMessage (dart:isolate-patch/isolate_patch.dart:184:12)

2. 未处理空检查异常

E/flutter ( 3573): [ERROR:flutter/runtime/dart_vm_initializer.cc(41)] Unhandled Exception: Null check operator used on a null value
E/flutter ( 3573): #0 _HotRestartFinalizer._finalize (package:iris_method_channel/src/platform/io/iris_method_channel_internal_io.dart:155:74)
E/flutter ( 3573): #1 _RootZone.runUnaryGuarded (dart:async/zone.dart:1594:10)
E/flutter ( 3573): #2 _BufferingStreamSubscription._sendData (dart:async/stream_impl.dart:339:11)
E/flutter ( 3573): #3 _BufferingStreamSubscription._add (dart:async/stream_impl.dart:271:7)
E/flutter ( 3573): #4 _SyncStreamControllerDispatch._sendData (dart:async/stream_controller.dart:784:19)
E/flutter ( 3573): #5 _StreamController._add (dart:async/stream_controller.dart:658:7)
E/flutter ( 3573): #6 _StreamController.add (dart:async/stream_controller.dart:606:5)
E/flutter ( 3573): #7 _RawReceivePort._handleMessage (dart:isolate-patch/isolate_patch.dart:184:12)

相关实现代码:

import 'dart:convert';
import 'package:flutter/services.dart';
import 'package:agora_rtc_engine/agora_rtc_engine.dart';
import 'package:permission_handler/permission_handler.dart';
import 'dart:async';
import 'package:flutter/material.dart';

class newww extends StatefulWidget {
  const newww({Key? key}) : super(key: key);

  @override
  State<newww> createState() => _newwwState();
}

class _newwwState extends State<newww> {
  int? _remoteUid;
  bool _localUserJoined = false;
  late RtcEngine _engine;

  @override
  void initState() {
    super.initState();
    initAgora();
  }

  Future<void> initAgora() async {
    // retrieve permissions
    await [Permission.microphone, Permission.camera].request();

    //create the engine
    _engine = createAgoraRtcEngine();
    await _engine.initialize(const RtcEngineContext(
      appId: "a28be509a7404ebc9f42459393ba1cfa",
      channelProfile: ChannelProfileType.channelProfileLiveBroadcasting,
    ));

    _engine.registerEventHandler(
      RtcEngineEventHandler(
        onJoinChannelSuccess: (RtcConnection connection, int elapsed) {
          debugPrint("local user ${connection.localUid} joined");
          setState(() {
            _localUserJoined = true;
          });
        },
        onUserJoined: (RtcConnection connection, int remoteUid, int elapsed) {
          debugPrint("remote user $remoteUid joined");
          setState(() {
            _remoteUid = remoteUid;
          });
        },
        onUserOffline: (RtcConnection connection, int remoteUid,
            UserOfflineReasonType reason) {
          debugPrint("remote user $remoteUid left channel");
          setState(() {
            _remoteUid = null;
          });
        },
        onTokenPrivilegeWillExpire: (RtcConnection connection, String token) {
          debugPrint(
              '[onTokenPrivilegeWillExpire] connection: ${connection.toJson()}, token: $token');
        },
      ),
    );

    await _engine.setClientRole(role: ClientRoleType.clientRoleBroadcaster);
    await _engine.enableVideo();
    await _engine.startPreview();

    await _engine.joinChannel(
      token: "007eJxTYDBL3aC4U2Hicl9Vsc4Eo0bx4z8K4u59u6EaeHiuVIObhK8CQ6KRRVKqqYFlormJgUlqUrJlmomRiamlsaVxUqJhclri6dXaaQ2BjAxJsreYGBkgEMRnYShJLS5hYAAAzAceCQ==",
      channelId: "test",
      uid: 0,
      options: const ChannelMediaOptions(),
    );
  }

  @override
  void dispose() {
    super.dispose();
    _dispose();
  }

  Future<void> _dispose() async {
    await _engine.leaveChannel();
    await _engine.release();
  }

  // Create UI with local view and remote view
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: const Text('Agora Video Call'),
      ),
      body: Stack(
        children: [
          Center(
            child: _remoteVideo(),
          ),
          Align(
            alignment: Alignment.topLeft,
            child: SizedBox(
              width: 100,
              height: 150,
              child: Center(
                child: _localUserJoined
                    ? AgoraVideoView(
                  controller: VideoViewController(
                    rtcEngine: _engine,
                    canvas: const VideoCanvas(uid: 0),
                  ),
                )
                    : const CircularProgressIndicator(),
              ),
            ),
          ),
        ],
      ),
    );
  }

  // Display remote user's video
  Widget _remoteVideo() {
    if (_remoteUid != null) {
      return AgoraVideoView(
        controller: VideoViewController.remote(
          rtcEngine: _engine,
          canvas: VideoCanvas(uid: _remoteUid),
          connection: const RtcConnection(channelId: "test"),
        ),
      );
    } else {
      return const Text(
        'Please wait for remote user to join',
        textAlign: TextAlign.center,
      );
    }
  }
}

解决方案

针对动态库加载失败

  • 清理重建项目:执行flutter clean清除缓存,再运行flutter pub get拉取依赖,最后重新编译。Android端可手动删除android/app/build目录后再构建。
  • 配置支持的ABI架构:在android/app/build.gradle的defaultConfig中添加NDK配置,确保包含Agora支持的架构:
    android {
      defaultConfig {
        ndk {
          abiFilters 'armeabi-v7a', 'arm64-v8a', 'x86_64'
        }
      }
    }
    
  • 调整依赖版本:尝试将agora_rtc_engine切换到6.2.0或最新稳定版,部分版本存在动态库打包疏漏问题。

针对空检查异常

  • 优化引擎释放逻辑:在_dispose方法中增加空值判断并捕获异常,避免操作未初始化的引擎:
    Future<void> _dispose() async {
      try {
        await _engine.leaveChannel();
        await _engine.release();
      } catch (e) {
        debugPrint('Engine dispose error: $e');
      }
    }
    
  • 避免热重启触发异常:该问题常出现在热重启后,测试时尽量使用冷启动;或在initState中确保每次初始化都是全新的引擎实例。
  • 延迟执行释放操作:在dispose中通过WidgetsBinding延迟执行清理,确保UI框架完成处理后再释放引擎:
    @override
    void dispose() {
      super.dispose();
      WidgetsBinding.instance.addPostFrameCallback((_) {
        _dispose();
      });
    }
    

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.24 09:18:10