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

Flutter集成Agora RTC Engine启动报错问题求助

Flutter集成Agora RTC Engine启动报错排查

问题描述

在Flutter应用中集成Agora RTC Engine时,每次启动项目调用joinChannel都会触发报错,报错信息如下:

E/flutter (22222): [ERROR:flutter/runtime/dart_vm_initializer.cc(41)] Unhandled Exception: PlatformException(joinChannel, joinChannel failed, error code: -1007, null, null)
E/flutter (22222): #0      MethodChannelAgoraRtcEngine.joinChannel (package:agora_rtc_engine/src/agora_rtc_engine.dart:1057:7)
E/flutter (22222): <asynchronous suspension>
E/flutter (22222): #1      _LiveStreamingState.join (package:ajanba/screens/live_streaming.dart:87:5)
E/flutter (22222): <asynchronous suspension>

报错代码-1007指向Token相关问题,但无法准确定位,以下是集成代码:

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

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

 @override
 _LiveStreamingState createState() => _LiveStreamingState();
}

class _LiveStreamingState extends State<LiveStreaming> {
 String appId = '4235f9d46dd349e0b9df3ad2ea011b7d';
 String channelName = "ajanba";
 String token = "007eJxTYHCe9kzt0Gtu0ZfqVv99H1YoVC06Yltmoth98HnQfaFEEX4FBhMjY9M0yxQTs5QUYxPLVIMky5Q048QUo9REA0PDJPOUtXmJyQ2BjAxxB+cyMzJAIIjPxpCYlZiXlMjAAABaqB+p";

 int uid = 0; // 本地用户uid
 int? _remoteUid; // 远程用户uid
 bool _isJoined = false; // 本地用户是否已加入频道
 bool _isHost = true; // 用户角色:主播/观众
 late RtcEngine agoraEngine; // Agora引擎实例

 final GlobalKey<ScaffoldMessengerState> scaffoldMessengerKey =
     GlobalKey<ScaffoldMessengerState>(); // 全局key用于显示SnackBar

 showMessage(String message) {
   scaffoldMessengerKey.currentState?.showSnackBar(SnackBar(
     content: Text(message),
   ));
 }

 @override
 void initState() {
   super.initState();
   // 初始化Agora引擎
   setupVideoSDKEngine();
 }

 Future<void> setupVideoSDKEngine() async {
   // 请求相机和麦克风权限
   await [Permission.microphone, Permission.camera].request();

   // 创建Agora引擎实例
   agoraEngine = createAgoraRtcEngine();
   await agoraEngine.initialize(RtcEngineContext(appId: appId));

   await agoraEngine.enableVideo();

   // 注册事件处理器
   agoraEngine.registerEventHandler(
     RtcEngineEventHandler(
       onJoinChannelSuccess: (RtcConnection connection, int elapsed) {
         showMessage("本地用户 uid:${connection.localUid} 已加入频道");
         setState(() {
           _isJoined = true;
         });
       },
       onUserJoined: (RtcConnection connection, int remoteUid, int elapsed) {
         showMessage("远程用户 uid:$remoteUid 已加入频道");
         setState(() {
           _remoteUid = remoteUid;
         });
       },
       onUserOffline: (RtcConnection connection, int remoteUid,
           UserOfflineReasonType reason) {
         showMessage("远程用户 uid:$remoteUid 已离开频道");
         setState(() {
           _remoteUid = null;
         });
       },
     ),
   );
 }

 void join() async {
   // 设置频道参数
   ChannelMediaOptions options;

   // 根据角色设置频道属性
   if (_isHost) {
     options = const ChannelMediaOptions(
       clientRoleType: ClientRoleType.clientRoleBroadcaster,
       channelProfile: ChannelProfileType.channelProfileLiveBroadcasting,
     );
     await agoraEngine.startPreview();
   } else {
     options = const ChannelMediaOptions(
       clientRoleType: ClientRoleType.clientRoleAudience,
       channelProfile: ChannelProfileType.channelProfileLiveBroadcasting,
     );
   }

   await agoraEngine.joinChannel(
     token: token,
     channelId: channelName,
     options: options,
     uid: uid,
   );
 }

 @override
 void dispose() async {
   await agoraEngine.leaveChannel();
   super.dispose();
 }

 void leave() {
   setState(() {
     _isJoined = false;
     _remoteUid = null;
   });
   agoraEngine.leaveChannel();
 }

 @override
 Widget build(BuildContext context) {
   return MaterialApp(
     scaffoldMessengerKey: scaffoldMessengerKey,
     home: Scaffold(
         appBar: AppBar(
           title: const Text('互动直播入门'),
         ),
         body: ListView(
           padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 4),
           children: [
             // 本地视频容器
             Container(
               height: 240,
               decoration: BoxDecoration(border: Border.all()),
               child: Center(child: _videoPanel()),
             ),
             // 角色选择单选按钮
             Row(children: <Widget>[
               Radio<bool>(
                 value: true,
                 groupValue: _isHost,
                 onChanged: (value) => _handleRadioValueChange(value),
               ),
               const Text('主播'),
               Radio<bool>(
                 value: false,
                 groupValue: _isHost,
                 onChanged: (value) => _handleRadioValueChange(value),
               ),
               const Text('观众'),
             ]),
             // 操作按钮行
             Row(
               children: <Widget>[
                 Expanded(
                   child: ElevatedButton(
                     child: const Text("加入"),
                     onPressed: () => {join()},
                   ),
                 ),
                 const SizedBox(width: 10),
                 Expanded(
                   child: ElevatedButton(
                     child: const Text("离开"),
                     onPressed: () => {leave()},
                   ),
                 ),
               ],
             ),
           ],
         )),
   );
 }

 Widget _videoPanel() {
   if (!_isJoined) {
     return const Text(
       '请加入频道',
       textAlign: TextAlign.center,
     );
   } else if (_isHost) {
     // 主播视角:显示本地视频
     return AgoraVideoView(
       controller: VideoViewController(
         rtcEngine: agoraEngine,
         canvas: VideoCanvas(uid: uid),
       ),
     );
   } else {
     // 观众视角:显示远程主播视频
     if (_remoteUid != null) {
       return AgoraVideoView(
         controller: VideoViewController.remote(
           rtcEngine: agoraEngine,
           canvas: VideoCanvas(uid: _remoteUid),
           connection: RtcConnection(channelId: channelName),
         ),
       );
     } else {
       return const Text(
         '等待主播加入',
         textAlign: TextAlign.center,
       );
     }
   }
 }

// 切换用户角色
 void _handleRadioValueChange(bool? value) async {
   setState(() {
     _isHost = (value == true);
   });
   if (_isJoined) leave();
 }
}

排查与解决方法

1. 验证Token有效性

Agora错误码-1007核心原因是Token无效,需确认:

  • Token生成时使用的appId、channelName、uid必须与代码中的完全一致
  • 检查Token有效期,测试Token默认有效期为24小时,过期需重新生成
  • 若使用Agora控制台生成的临时Token,确保频道名完全匹配,临时Token仅对指定频道生效

2. 检查App ID配置

  • 确认代码中的appId与Agora控制台获取的一致,无拼写错误
  • 登录Agora控制台,检查该App ID是否已启用实时音视频服务

3. 确认权限配置

代码中已请求动态权限,但需确保原生配置文件添加了必要权限:

  • Android:在android/app/src/main/AndroidManifest.xml中添加:
    <uses-permission android:name="android.permission.INTERNET" />
    <uses-permission android:name="android.permission.CAMERA" />
    <uses-permission android:name="android.permission.RECORD_AUDIO" />
    <uses-permission android:name="android.permission.MODIFY_AUDIO_SETTINGS" />
    <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
    
  • iOS:在ios/Runner/Info.plist中添加:
    <key>NSCameraUsageDescription</key>
    <string>需要使用相机进行直播</string>
    <key>NSMicrophoneUsageDescription</key>
    <string>需要使用麦克风进行直播</string>
    

4. 优化引擎初始化流程

  • 在setupVideoSDKEngine中添加错误捕获,确认引擎初始化成功:
    Future<void> setupVideoSDKEngine() async {
      await [Permission.microphone, Permission.camera].request();
      agoraEngine = createAgoraRtcEngine();
      try {
        await agoraEngine.initialize(RtcEngineContext(appId: appId));
        await agoraEngine.enableVideo();
        // 注册事件处理器...
      } catch (e) {
        showMessage("引擎初始化失败: $e");
      }
    }
    
  • 确保调用joinChannel前,引擎初始化已完成

5. 网络环境检查

  • 确认设备网络连接正常,Agora服务需要稳定的公网连接
  • 若处于企业内网,需确保防火墙允许访问Agora的服务器地址

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.14 03:50:47