Flutter即时通讯插件rongcloud_call_wrapper_plugin的使用

Flutter即时通讯插件rongcloud_call_wrapper_plugin的使用

1. 快速实现音视频通话 CallLib

CallLib 是在 RTCLib 基础上,额外封装了一套音视频呼叫功能 SDK,包含了单人视频呼叫的各种场景和功能,通过集成它,您可以自由地实现音视频呼叫场景的各种玩法。

2. 步骤 1:服务开通

您在融云创建的应用默认不会启用音视频服务。在使用融云提供的任何音视频服务前,您需要前往开发者后台,为应用开通音视频服务。

3. 步骤 2:SDK 导入

您需要导入融云音视频通话能力库 CallLib。

具体步骤请参阅:

flutter pub add rongcloud_call_wrapper_plugin

执行命令后将在项目配置文件 pubspec.yaml 中增加以下代码:

dependencies:
  rongcloud_call_wrapper_plugin: 5.12.0

在代码中导入 Call Lib:

import 'package:rongcloud_call_wrapper_plugin/rongcloud_call_wrapper_plugin.dart';

4. 步骤 3:权限配置

Android

请在 AndroidManifest.xml 文件中添加摄像头、麦克风与网络的申请权限:

<!-- 音视频需要网络权限 和 监听网络状态权限 -->
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.CHANGE_NETWORK_STATE" />
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
<!-- 摄像头采集需要 -->
<uses-permission android:name="android.permission.CAMERA" />
<!-- 音频采集需要 -->
<uses-permission android:name="android.permission.RECORD_AUDIO" />
<uses-permission android:name="android.permission.MODIFY_AUDIO_SETTINGS" />
iOS

请在 Info.plist 文件中添加摄像头和麦克风的申请权限:

<key>NSCameraUsageDescription</key>
<string>摄像头权限使用描述</string>
<key>NSMicrophoneUsageDescription</key>
<string>麦克风权限使用描述</string>

5. 步骤 4:初始化

音视频 SDK 是基于即时通信 SDK 作为信令通道的,所以要先初始化 IM SDK。如果不换 AppKey,在整个应用生命周期中,初始化一次即可。

RongIMClient.init('从开发者后台申请的 AppKey');

6. 步骤 5:连接 IM 服务

音视频用户之间的信令传输依赖于融云的即时通信(IM)服务,因此需要先调用 connect 与 IM 服务建立好 TCP 长连接。建议在功能模块的加载位置处调用,之后再进行音视频呼叫业务。当模块退出后调用 disconnectlogout 断开该连接。

RongIMClient.connect('从您服务器端获取的 Token', (code, id) {
  if (code == RCErrorCode.Success) {
    // 连接成功
  } else {
    // 连接失败
  }
});

如调用此接口时,遇到网络不好导致连接失败,SDK 会自动启动重连机制进行最多 10 次重连,重连时间间隔分别为 1, 2, 4, 8, 16, 32, 64, 128, 256, 512 秒。在这之后如果仍没有连接成功,还会在检测到设备网络状态变化,比如网络恢复或切换网络时再次尝试重连。

如 App 在被杀死后,接收到了推送通知,点击通知拉起应用时,需要再次调用 connect 方法进行连接。

7. 步骤 6:通话事件处理

开发者可通过设置 RCCallEngine 中的 onReceiveCall 方法来监听通话呼入。

engine?.onReceiveCall = (RCCallSession session) {
    /// session 通话实体
};

开发者可通过设置 RCCallEngine 中的 onCallDidMakeonConnect 以及 onDisconnect 方法来监听通话状态的变化。

/// 通话拨出监听
engine?.onCallDidMake = () {
};

/// 通话建立监听
engine?.onConnect = () {
};

/// 通话断开监听
engine?.onDisconnect = (RCCallDisconnectReason reason) {
    /// reason 断开原因
};

8. 步骤 7:发起呼叫

连接 IM 服务成功后,可调用 RCCallEngine 中的 startCall 方法发起通话。

单人通话代码示例:
/// 被叫用户 Id
String targetId = 'UserB';
/// 通话媒体类型
RCCallMediaType mediaType = RCCallMediaType.audio_video;
engine?.startCall(targetId, mediaType);
指定摄像头发起呼叫

发起单人音视频通话需要打开指定摄像头,请参考以下代码。

RCCallVideoConfig videoConfig = RCCallVideoConfig.create(
  /// 指定开启后置摄像头
  defaultCamera: RCCallCamera.back, 
);
/// 配置视频参数
engine?.setVideoConfig(videoConfig); 
/// 被叫用户 Id
String targetId = 'UserB';
/// 通话媒体类型
RCCallMediaType mediaType = RCCallMediaType.audio_video;
engine?.startCall(targetId, mediaType);

9. 步骤 8:呼叫接听

在收到 onReceiveCall(RCCallSession session) 回调之后,调用如下方法接听通话。

engine?.accept();
指定摄像头接听

来电监听中接收到来电请求后,调用以下代码接听通话,可以打开指定摄像头。

engine?.onReceiveCall = (RCCallSession session) {
    RCCallVideoConfig videoConfig = RCCallVideoConfig.create(
    /// 指定开启后置摄像头
    defaultCamera: RCCallCamera.back, 
    );
    /// 配置视频参数
    engine?.setVideoConfig(videoConfig); 
    engine?.accept();
};

10. 步骤 9:离线推送通知

集成离线推送后,即使 App 已经被系统回收,也可以收到呼叫的推送通知。详细请参考 Android 、 iOS 远程推送集成文档。

通话管理

主叫方

发起呼叫

调用 RCCallEngine.startCall 方法发起单人或多人音视频通话,该方法默认打开前置摄像头。

参数说明:
参数 类型 必填 说明
targetId String 目标 UserId
mediaType RCCallMediaType 发起的通话媒体类型
extra String 附加信息,透传至对端
示例代码:
/// 被叫用户 Id
String targetId = 'UserB';
/// 通话媒体类型
RCCallMediaType mediaType = RCCallMediaType.audio_video;
/// 扩展信息
String extra = '';
engine?.startCall(targetId, mediaType, extra);
指定摄像头发起呼叫

发起单人音视频通话需要打开指定摄像头,请参考以下代码。

示例代码:
RCCallVideoConfig videoConfig = RCCallVideoConfig.create(
  /// 指定开启后置摄像头
  defaultCamera: RCCallCamera.back, 
);
/// 配置视频参数
engine?.setVideoConfig(videoConfig); 
/// 被叫用户 Id
String targetId = 'UserB';
/// 通话媒体类型
RCCallMediaType mediaType = RCCallMediaType.audio_video;
/// 扩展信息
String extra = '';
engine?.startCall(targetId, mediaType, extra);
挂断通话

调用 RCCallEngine.hangup 方法挂断通话,拒绝和挂断为同一个方法调用,SDK 内部会自动告知对方挂断、拒绝原因。

示例代码:
engine?.hangup();

被叫方

接听通话
默认接听

当收到来自 onReceiveCall 的远端通话请求时,可使用 RCCallEngineaccept 方法来接听。

示例代码:
engine?.onReceiveCall = (RCCallSession session) {
    engine?.accept();
};
指定摄像头接听

来电监听中接收到来电请求后,调用以下代码接听通话,可以打开指定摄像头。

示例代码:
engine?.onReceiveCall = (RCCallSession session) {
    RCCallVideoConfig videoConfig = RCCallVideoConfig.create(
    /// 指定开启后置摄像头
    defaultCamera: RCCallCamera.back, 
    );
    /// 配置视频参数
    engine?.setVideoConfig(videoConfig); 
    engine?.accept();
};
拒绝/挂断通话

调用 RCCallEngine.hangup 方法挂断通话,拒绝和挂断为同一个方法调用,SDK 内部会自动告知对方挂断、拒绝原因。

示例代码:
engine?.hangup();

通话监听

来电监听

示例代码:
/// 设置来电回调
engine?.onReceiveCall = (RCCallSession session) {
    /// session 通话实体
};

通话拨出监听

示例代码:
/// 设置通话拨出监听
engine?.onCallDidMake = () {
};

通话建立监听

示例代码:
/// 设置通话建立监听
engine?.onConnect = () {
};

通话断开监听

示例代码:
/// 设置通话断开监听
engine?.onDisconnect = (RCCallDisconnectReason reason) {
    /// reason 断开原因
};

通话异常监听

示例代码:
/// 设置通话异常监听
engine?.onCallError = (int errorCode) {
    /// errorCode 异常错误码
};

摄像头操作监听

示例代码:
/// 设置摄像头操作监听
engine?.onEnableCamera = (RCCallCamera camera, bool enable) {
    /// camera 当前摄像头
    /// enable 开启状态
};

切换摄像头监听

示例代码:
/// 设置切换摄像头监听
engine?.onSwitchCamera = (RCCallCamera camera) {
    /// camera 当前摄像头
};

被叫端正在振铃监听

示例代码:
/// 设置被叫端正在振铃监听
engine?.onRemoteUserDidRing = (String userId) {
    /// userId 正在振铃的用户 ID
};

用户操作麦克风监听

示例代码:
/// 设置用户操作麦克风监听
engine?.onRemoteUserDidChangeMicrophoneState = (RCCallUserProfile user, bool enable) {
    /// user 操作麦克风的用户
    /// enable 麦克风开启状态
};

用户操作摄像头监听

示例代码:
/// 设置用户操作摄像头监听
engine?.onRemoteUserDidChangeCameraState = (RCCallUserProfile user, bool enable) {
    /// user 操作摄像头的用户
    /// enable 摄像头开启状态
};

视频转音频监听

示例代码:
/// 设置视频转音频监听
engine?.onRemoteUserDidChangeMediaType = (RCCallUserProfile user, RCCallMediaType mediaType) {
    /// user 触发媒体类型转换的用户
    /// mediaType 转换后的媒体类型
};

通话网络质量监听

示例代码:
/// 设置通话网络质量监听
engine?.onNetworkQuality = (RCCallUserProfile user, RCCallNetworkQuality quality) {
    /// user 用户信息
    /// quality 网络质量
};

通话音量监听

示例代码:
/// 设置通话音量监听
engine?.onAudioVolume = (RCCallUserProfile user, int volume) {
    /// user 用户信息
    /// volume 当前音量
};

通话挂断原因

枚举值 平台 说明
cancel Android/iOS 己方取消已发出的通话请求
reject Android/iOS 己方拒绝收到的通话请求
hangup Android/iOS 己方挂断
busy_line Android/iOS 己方忙碌
no_response Android/iOS 己方未接听
engine_unsupported Android/iOS 己方不支持当前引擎
network_error Android/iOS 己方网络出错
resource_error iOS 己方获取媒体资源失败
publish_error iOS 己方发布资源失败
subscribe_error iOS 己方订阅资源失败
remote_cancel Android/iOS 对方取消已发出的通话请求
remote_reject Android/iOS 对方拒绝收到的通话请求
remote_hangup Android/iOS 通话过程对方挂断
remote_busy_line Android/iOS 对方忙碌
remote_no_response Android/iOS 对方未接听
remote_engine_unsupported Android/iOS 对方不支持当前引擎
remote_network_error Android/iOS 对方网络错误
remote_resource_error iOS 对方获取媒体资源失败
remote_publish_error iOS 对方发布资源失败
remote_subscribe_error iOS 对方订阅资源失败
kicked_by_other_call iOS 己方其他端已加入新通话
in_other_call iOS 己方其他端已在通话中
kicked_by_server Android/iOS 己方已被禁止通话
remote_kicked_by_other_call iOS 对方其他端已加入新通话
remote_in_other_call iOS 对方其他端已在通话中
remote_kicked_by_server iOS 对方已被禁止通话
accept_by_other_client iOS 己方其他端已接听
hangup_by_other_client iOS 己方其他端已挂断
add_to_black_list Android/iOS 己方被对方加入黑名单
media_server_closed Android/iOS 音视频服务已关闭
degrade iOS 己方被降级为观察者
init_video_error Android 己方摄像头初始化错误,可能是没有打开使用摄像头权限
other_device_had_accepted Android 其他端已经接听
service_disconnected Android im ipc服务已断开

通话错误原因

状态码 平台 说明
0 Android/iOS 成功
1 Android 开通的音视频服务没有及时生效或音视频服务已关闭
2 iOS 网络不可用
3 iOS 已经处于通话中了
4 iOS 无效操作
5 iOS 参数错误
6 iOS 网络不稳定
7 iOS 媒体服务请求失败
8 iOS 媒体服务初始化失败
9 iOS 媒体服务未初始化
10 iOS 媒体服务请求超时
11 iOS 未知的媒体服务错误
12 iOS 已被禁止通话
13 iOS 音视频服务已关闭
14 iOS 音视频发布资源失败
15 iOS 音视频订阅资源失败
16 iOS 其他端已在通话中错误

视频管理

视频参数设置

在发起通话和接听通话前,调用 setVideoConfig 设置音视频通话采用的分辨率、帧率以及码率。默认值为 profile_480_640_high,前置摄像头。

示例代码:
RCCallVideoConfig videoConfig = RCCallVideoConfig.create(
  /// 设置视频分辨率为 1080p,帧率 30 fps,码率 800 ~ 8000 kbps
  profile: RCCallVideoProfile.profile_1080_1920_high,
);
engine?.setVideoConfig(videoConfig);

摄像头设置

配置默认开启的摄像头

在发起通话和接听通话前,调用 setVideoConfig 设置默认开启的摄像头,默认配置为 RCCallCamera.front。

示例代码:
RCCallVideoConfig videoConfig = RCCallVideoConfig.create(
  /// 指定开启后置摄像头
  defaultCamera: RCCallCamera.back, 
);
/// 配置视频参数
engine?.setVideoConfig(videoConfig); 
开关摄像头

在通话建立(RCCallEngine.onConnect)之后操作摄像头,对端会收到 RCCallEngine.onRemoteUserDidChangeCameraState 通知。

示例代码:
/// 关闭摄像头
engine?.enableCamera(false);
切换前后置摄像头

在通话建立(RCCallEngine.onConnect)之后,调用 switchCamera() 方法切换前后置摄像头,该方法适用于通过 SDK 打开默认摄像头的场景,配合 RCCallEngine.startCall 使用,startCall 方法默认打开前置摄像头。

示例代码:
engine?.switchCamera();

视频转音频

当用户希望从视频通话转为音频时,可以调用 RCCallEnginechangeMediaType 方法。目前仅支持视频单向往音频转换,即参数只能为 RCCallMediaType.audio

示例代码:
engine?.changeMediaType(RCCallMediaType.audio);

美颜处理

在 Flutter CallLib 中封装了融云提供的美颜插件,可以通过以下接口实现美颜功能。美颜参数设置分为基础值设置和滤镜设置。

美颜基础参数

基础参数目前包括:美白、磨皮、亮度、红润四个参数,取值范围为 [0-9],0 代表无效果,9 代表最大效果。代码示例如下:

RCCallBeautyOption option = RCCallBeautyOption.create(
  /// 设置美白参数
  whitenessLevel: whiteness,
  /// 设置磨皮参数
  smoothLevel: smooth,
  /// 设置红润参数
  ruddyLevel: ruddy,
  /// 设置亮度参数
  brightLevel: bright,
);
/// 设置美颜参数和美颜开关 true 是使用美颜,false 不使用美颜
engine?.setBeautyOption(option, true);
美颜滤镜设置

滤镜目前包括:唯美、清新、浪漫三种风格,代码示例如下:

/// 不使用美颜滤镜
engine?.setBeautyFilter(RCCallBeautyFilter.none);
/// 唯美滤镜
engine?.setBeautyFilter(RCCallBeautyFilter.esthetic);
/// 清新滤镜
engine?.setBeautyFilter(RCCallBeautyFilter.fresh);
/// 浪漫滤镜
engine?.setBeautyFilter(RCCallBeautyFilter.romantic);

音频管理

麦克风设置

打开/关闭麦克风

当通话中希望关闭麦克风,可调用 RCCallEngineenableMicrophone 接口,传入 false 达到本地静音效果;当需要再次打开时,传入 true 即可。默认值为 true,即麦克风打开状态。

engine?.enableMicrophone(true);

扬声器设置

听筒/扬声器切换

当通话中希望切换声音播放是由扬声器还是听筒输出时,可调用 RCCallEngineenableSpeaker 来设置。传入 true 代表使用扬声器播放;false 代表使用听筒播放。默认是 false 即使用听筒播放。

示例代码:
engine?.enableSpeaker(false);

注:此接口在收到 RCCallEngine.onConnect() 回调之后调用才有效。

示例代码

import 'package:flutter/services.dart';
import 'package:flutter/material.dart';

import 'package:context_holder/context_holder.dart';
// import 'package:wakelock/wakelock.dart';

import 'package:flutter_call_plugin_example/frame/utils/local_storage.dart';
import 'global_config.dart';
import 'router/router.dart';

void main() {
  // 确保Flutter已初始化。
  WidgetsFlutterBinding.ensureInitialized();
  
  // 初始化本地存储,然后运行应用程序。
  LocalStorage.init().then((value) => runApp(const RCCallFlutter()));
}

class RCCallFlutter extends StatelessWidget {
  const RCCallFlutter({Key? key}) : super(key: key);

  [@override](/user/override)
  Widget build(BuildContext context) {
    // 设置首选方向为垂直向上和垂直向下。
    SystemChrome.setPreferredOrientations([
      DeviceOrientation.portraitUp,
      DeviceOrientation.portraitDown,
    ]);

    // 定义系统UI叠加样式,包括透明状态栏和暗色图标。
    SystemUiOverlayStyle systemUiOverlayStyle = const SystemUiOverlayStyle(
      statusBarColor: Colors.transparent,
      statusBarIconBrightness: Brightness.dark,
    );
    SystemChrome.setSystemUIOverlayStyle(systemUiOverlayStyle);

    // 启用设备唤醒锁定。
    // Wakelock.enable();

    return MaterialApp(
      // 使用Context Holder插件的导航键。
      navigatorKey: ContextHolder.key,
      // 设置应用程序的标题。
      title: GlobalConfig.appTitle,
      // 设置应用程序的主题数据。
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      // 设置应用程序的初始路由。
      initialRoute: RouterManager.CONNECT,
      // 初始化路由表。
      routes: RouterManager.initRouters(),
      // 注释掉的部分可以用于添加导航观察器。
      // navigatorObservers: [
      //   LeakNavigatorObserver(),
      // ],
    );
  }
}

更多关于Flutter即时通讯插件rongcloud_call_wrapper_plugin的使用的实战教程也可以访问 https://www.itying.com/category-92-b0.html

1 回复

更多关于Flutter即时通讯插件rongcloud_call_wrapper_plugin的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html


rongcloud_call_wrapper_plugin 是一个用于在 Flutter 应用中集成融云(RongCloud)音视频通话功能的插件。通过这个插件,开发者可以轻松地在 Flutter 应用中实现音视频通话功能。

以下是使用 rongcloud_call_wrapper_plugin 的基本步骤:

1. 添加依赖

首先,在 pubspec.yaml 文件中添加 rongcloud_call_wrapper_plugin 插件的依赖:

dependencies:
  flutter:
    sdk: flutter
  rongcloud_call_wrapper_plugin: ^版本号

请将 版本号 替换为最新的插件版本号。

2. 初始化融云 SDK

在应用启动时,初始化融云 SDK。通常可以在 main.dart 中进行初始化:

import 'package:rongcloud_call_wrapper_plugin/rongcloud_call_wrapper_plugin.dart';

void main() async {
  WidgetsFlutterBinding.ensureInitialized();
  
  // 初始化融云 SDK
  await RongcloudCallWrapperPlugin.init("YourAppKey");
  
  runApp(MyApp());
}

"YourAppKey" 替换为你在融云开发者平台注册的应用 AppKey。

3. 配置音视频通话

在需要进行音视频通话的地方,配置并启动通话:

import 'package:rongcloud_call_wrapper_plugin/rongcloud_call_wrapper_plugin.dart';

class CallPage extends StatefulWidget {
  final String targetUserId;

  CallPage({required this.targetUserId});

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

class _CallPageState extends State<CallPage> {
  @override
  void initState() {
    super.initState();
    startCall();
  }

  void startCall() async {
    // 启动音视频通话
    await RongcloudCallWrapperPlugin.startCall(
      widget.targetUserId,
      CallMediaType.Video, // 通话类型,可以是 CallMediaType.Video 或 CallMediaType.Audio
    );
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('通话中'),
      ),
      body: Center(
        child: Text('正在与 ${widget.targetUserId} 通话中...'),
      ),
    );
  }
}

4. 处理通话状态

你可以监听通话状态的变化,并根据状态更新 UI 或执行其他操作:

RongcloudCallWrapperPlugin.onCallStateChanged.listen((CallState state) {
  switch (state.callStatus) {
    case CallStatus.CallConnected:
      // 通话已连接
      break;
    case CallStatus.CallEnded:
      // 通话已结束
      break;
    case CallStatus.CallFailed:
      // 通话失败
      break;
    // 其他状态处理
  }
});

5. 结束通话

在通话结束时,可以调用 endCall 方法结束通话:

await RongcloudCallWrapperPlugin.endCall();

6. 其他功能

rongcloud_call_wrapper_plugin 还提供了其他功能,如切换摄像头、静音、免提等。你可以根据需要使用这些功能:

// 切换摄像头
await RongcloudCallWrapperPlugin.switchCamera();

// 静音
await RongcloudCallWrapperPlugin.muteAudio(true);

// 免提
await RongcloudCallWrapperPlugin.enableSpeakerphone(true);

7. 错误处理

在使用过程中,可能会遇到一些错误,建议在使用时进行错误捕获和处理:

try {
  await RongcloudCallWrapperPlugin.startCall(widget.targetUserId, CallMediaType.Video);
} catch (e) {
  print("Error starting call: $e");
}
回到顶部