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

Flutter集成Agora视频通话遇cRallIrisApiWithUin8ListAsync方法未定义问题

问题

在Flutter集成Agora视频通话功能时,遇到错误:Error: The method 'cRallIrisApiWithUin8ListAsync' isn't defined for the class 'ApiCaller'。执行flutter pub cache repair后错误暂时消失,但重新运行应用时问题再次出现。

相关代码如下:

import 'package:agora_rtc_engine/agora_rtc_engine.dart';
import 'package:chat_in_english/ui/screens/dashboard/video%20broadcoast/example_actions_widget.dart';
import 'package:chat_in_english/ui/screens/dashboard/video%20broadcoast/log_sink.dart';
import 'package:chat_in_english/ui/screens/dashboard/video broadcoast/config.dart'
    as config;
import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';

/// MultiChannel Example
class JoinChannelVideo extends StatefulWidget {
  /// Construct the [JoinChannelVideo]
  const JoinChannelVideo({Key? key}) : super(key: key);

  @override
  State<StatefulWidget> createState() => _State();
}

class _State extends State<JoinChannelVideo> {
  late final RtcEngine _engine;
  bool _isReadyPreview = false;

  bool isJoined = false, switchCamera = true, switchRender = true;
  Set<int> remoteUid = {};
  late TextEditingController _controller;
  bool _isUseFlutterTexture = false;
  bool _isUseAndroidSurfaceView = false;
  ChannelProfileType _channelProfileType =
      ChannelProfileType.channelProfileLiveBroadcasting;

  @override
  void initState() {
    super.initState();
    _controller = TextEditingController(text: 'test channel');

    _initEngine();
  }

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

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

  Future<void> _initEngine() async {
    _engine = createAgoraRtcEngine();
    await _engine.initialize(RtcEngineContext(
      appId: 'b3bee66900fd4bc9af9622016796c74b',
    ));

    _engine.registerEventHandler(RtcEngineEventHandler(
      onError: (ErrorCodeType err, String msg) {
        logSink.log('[onError] err: $err, msg: $msg');
      },
      onJoinChannelSuccess: (RtcConnection connection, int elapsed) {
        logSink.log(
            '[onJoinChannelSuccess] connection: ${connection.toJson()} elapsed: $elapsed');
        setState(() {
          isJoined = true;
        });
      },
      onUserJoined: (RtcConnection connection, int rUid, int elapsed) {
        logSink.log(
            '[onUserJoined] connection: ${connection.toJson()} remoteUid: $rUid elapsed: $elapsed');
        setState(() {
          remoteUid.add(rUid);
        });
      },
      onUserOffline:
          (RtcConnection connection, int rUid, UserOfflineReasonType reason) {
        logSink.log(
            '[onUserOffline] connection: ${connection.toJson()}  rUid: $rUid reason: $reason');
        setState(() {
          remoteUid.removeWhere((element) => element == rUid);
        });
      },
      onLeaveChannel: (RtcConnection connection, RtcStats stats) {
        logSink.log(
            '[onLeaveChannel] connection: ${connection.toJson()} stats: ${stats.toJson()}');
        setState(() {
          isJoined = false;
          remoteUid.clear();
        });
      },
    ));

    await _engine.enableVideo();

    await _engine.setVideoEncoderConfiguration(
      const VideoEncoderConfiguration(
        dimensions: VideoDimensions(width: 640, height: 360),
        frameRate: 15,
        bitrate: 0,
      ),
    );

    await _engine.startPreview();

    setState(() {
      _isReadyPreview = true;
    });
  }

  Future<void> _joinChannel() async {
    await _engine.joinChannel(
      token: '007eJxTYLi8+O6xxal5ZRuW9B6yMYgKuHIoqmzu2qdf49sDMr4lxDIrMCQZJ6WmmplZGhikpZgkJVsmplmaGRkZGJqZW5olm5sk+RuXJDcEMjJ0+YgwMTJAIIjPw1CSWlyikJyRmJeXmsPAAAAB1SNY',
      channelId: _controller.text,
      uid: config.uid,
      options: ChannelMediaOptions(
        channelProfile: _channelProfileType,
        clientRoleType: ClientRoleType.clientRoleBroadcaster,
      ),
    );
  }

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

  Future<void> _switchCamera() async {
    await _engine.switchCamera();
    setState(() {
      switchCamera = !switchCamera;
    });
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: ExampleActionsWidget(
        displayContentBuilder: (context, isLayoutHorizontal) {
          if (!_isReadyPreview) return Container();
          return Stack(
            children: [
              AgoraVideoView(
                controller: VideoViewController(
                  rtcEngine: _engine,
                  canvas: const VideoCanvas(uid: 0),
                  useFlutterTexture: _isUseFlutterTexture,
                  useAndroidSurfaceView: _isUseAndroidSurfaceView,
                ),
              ),
              Align(
                alignment: Alignment.topLeft,
                child: SingleChildScrollView(
                  scrollDirection: Axis.horizontal,
                  child: Row(
                    children: List.of(remoteUid.map(
                          (e) => SizedBox(
                        width: 120,
                        height: 120,
                        child: AgoraVideoView(
                          controller: VideoViewController.remote(
                            rtcEngine: _engine,
                            canvas: VideoCanvas(uid: e),
                            connection:
                            RtcConnection(channelId: _controller.text),
                            useFlutterTexture: _isUseFlutterTexture,
                            useAndroidSurfaceView: _isUseAndroidSurfaceView,
                          ),
                        ),
                      ),
                    )),
                  ),
                ),
              )
            ],
          );
        },
        actionsBuilder: (context, isLayoutHorizontal) {
          final channelProfileType = [
            ChannelProfileType.channelProfileLiveBroadcasting,
            ChannelProfileType.channelProfileCommunication,
          ];
          final items = channelProfileType
              .map((e) => DropdownMenuItem(
            child: Text(
              e.toString().split('.')[1],
            ),
            value: e,
          ))
              .toList();

          return Column(
            mainAxisAlignment: MainAxisAlignment.start,
            crossAxisAlignment: CrossAxisAlignment.start,
            mainAxisSize: MainAxisSize.min,
            children: [
              TextField(
                controller: _controller,
                decoration: const InputDecoration(hintText: 'Channel ID'),
              ),
              if (!kIsWeb &&
                  (defaultTargetPlatform == TargetPlatform.android ||
                      defaultTargetPlatform == TargetPlatform.iOS))
                Row(
                  mainAxisSize: MainAxisSize.min,
                  mainAxisAlignment: MainAxisAlignment.start,
                  children: [
                    if (defaultTargetPlatform == TargetPlatform.iOS)
                      Column(
                          mainAxisAlignment: MainAxisAlignment.start,
                          crossAxisAlignment: CrossAxisAlignment.start,
                          mainAxisSize: MainAxisSize.min,
                          children: [
                            const Text('Rendered by Flutter texture: '),
                            Switch(
                              value: _isUseFlutterTexture,
                              onChanged: isJoined
                                  ? null
                                  : (changed) {
                                setState(() {
                                  _isUseFlutterTexture = changed;
                                });
                              },
                            )
                          ]),
                    if (defaultTargetPlatform == TargetPlatform.android)
                      Column(
                          mainAxisAlignment: MainAxisAlignment.start,
                          crossAxisAlignment: CrossAxisAlignment.start,
                          mainAxisSize: MainAxisSize.min,
                          children: [
                            const Text('Rendered by Android SurfaceView: '),
                            Switch(
                              value: _isUseAndroidSurfaceView,
                              onChanged: isJoined
                                  ? null
                                  : (changed) {
                                setState(() {
                                  _isUseAndroidSurfaceView = changed;
                                });
                              },
                            ),
                          ]),
                  ],
                ),
              const SizedBox(
                height: 20,
              ),
              const Text('Channel Profile: '),
              DropdownButton<ChannelProfileType>(
                items: items,
                value: _channelProfileType,
                onChanged: isJoined
                    ? null
                    : (v) {
                  setState(() {
                    _channelProfileType = v!;
                  });
                },
              ),
              const SizedBox(
                height: 20,
              ),
              Row(
                children: [
                  Expanded(
                    flex: 1,
                    child: ElevatedButton(
                      onPressed: isJoined ? _leaveChannel : _joinChannel,
                      child: Text('${isJoined ? 'Leave' : 'Join'} channel'),
                    ),
                  )
                ],
              ),
              if (defaultTargetPlatform == TargetPlatform.android ||
                  defaultTargetPlatform == TargetPlatform.iOS) ...[
                const SizedBox(
                  height: 20,
                ),
                ElevatedButton(
                  onPressed: _switchCamera,
                  child: Text('Camera ${switchCamera ? 'front' : 'rear'}'),
                ),
              ],
            ],
          );
        },
      ),
    );
  }
}

错误截图:
错误截图

彻底解决办法

这个错误是Agora SDK版本不兼容或依赖缓存冲突导致的,按以下步骤彻底修复:

  • 锁定兼容的Agora SDK版本
    打开pubspec.yaml,将agora_rtc_engine指定为稳定兼容版本,比如验证可用的^6.3.0(避免使用最新的不稳定版本):

    dependencies:
      agora_rtc_engine: ^6.3.0
    
  • 彻底清理依赖缓存
    执行以下命令清除旧缓存和依赖:

    flutter clean
    flutter pub get
    # macOS/Linux用户额外执行:
    rm -rf ~/.pub-cache/hosted/pub.dartlang.org/agora_rtc_engine-*
    # Windows用户额外执行:
    rd /s /q %USERPROFILE%\.pub-cache\hosted\pub.dartlang.org\agora_rtc_engine-*
    
  • 修复路径特殊字符问题
    你的代码中导入路径包含空格(如video broadcoast),可能引发依赖解析异常。重命名文件夹为video_broadcast,并修正导入路径:

    import 'package:chat_in_english/ui/screens/dashboard/video_broadcast/example_actions_widget.dart';
    import 'package:chat_in_english/ui/screens/dashboard/video_broadcast/log_sink.dart';
    import 'package:chat_in_english/ui/screens/dashboard/video_broadcast/config.dart' as config;
    
  • 验证原生依赖匹配
    iOS用户删除Podfile.lock后执行pod install;Android用户清理项目根目录的.gradle文件夹,确保原生SDK版本与Flutter插件版本匹配。

  • 重新构建项目
    完成以上步骤后,执行flutter run重新构建应用,确保所有依赖正确加载。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.12 01:25:20