乐趣区

关于音视频:如何基于-ZEGO-SDK-实现-Flutter-一对一音视频聊天应用

之前的文章公布了 ZEGO SDK 实现 Android 端音视频通话利用的开发教程,不少开发者反馈很实用,能不能也出一版 Flutter 的教程。

有求必应,这不小编来了~

咱们封装了 ZEGO Flutter SDK,本文将疏导你如何应用 ZEGO Flutter SDK 疾速轻松的构建一个跨平台音视频聊天利用, 缩小开发成本。

1 筹备环境

在开始集成 ZEGO Express SDK 前,请确保开发环境满足以下要求:

  • Flutter 1.12 或以上版本。
  • iOS 7.0 或以上版本,且反对音视频的 iOS 设施或模拟器(举荐应用真机)。
  • Android4.4 或以上版本,且反对音视频的 Android 设施或模拟器(举荐应用真机)。如果为真机,请开启“容许调试”选项。
  • iOS / Android 设施曾经连贯到 Internet。

请配置开发环境如下:

  • Android Studio:“Preferences > Plugins”,搜寻“Flutter”插件进行下载,并在插件中配置曾经下载好的 Flutter 的 SDK 门路。
  • VS Code: 在利用商店中搜寻“Flutter”扩大并下载。

以上任一开发环境配置好 Flutter 环境后,在终端执行 flutter doctor,依据提醒内容补全相干未下载的依赖项。

2 我的项目筹备

2.1 创立我的项目

进入 即构官网,在创立我的项目,【ZEGO 控制台】. 并申请无效的 AppID,这一步很要害,appid 为利用的惟一标识,如身份证号,是利用的身份证明,用于明确你的我的项目及组织身份。zego 提供的服务也是基于 APP ID;

App ID 的获取形式很简略,只需 3~5 分钟,在即构官网 - 我的我的项目 - 创立即可。创立的我的项目信息可用于 SDK 的集成和配置;

2.2 Token 鉴权

登录房间时必须 应用 Token 鉴权,可参考 Token 鉴权 教程。
为了不便开发阶段的调试,开发者可间接在 ZEGO 控制台获取长期 Token(有效期为 24 小时)来应用,详情请参考 控制台(新版)– 项目管理 中的“我的项目信息”。.

3 集成

3.1 我的项目设置

开始集成前,请参考 Flutter 文档 – Get Started. 创立一个 Flutter 我的项目。
如已有我的项目,本步骤可疏忽;

接下来咱们须要对我的项目做一下简略的配置,便于导入和应用 ZEGO Flutter SDK。

3.2 导入 SDK

关上“pubspec.yaml”文件,增加“zego_express_engine”依赖,有以下两种模式:

  • 以“pub”模式依赖(举荐):
dependencies:
flutter:
sdk: flutter

zego_express_engine: ^2.0.0
  • 以“git”模式依赖:
dependencies:
flutter:
sdk: flutter

zego_express_engine:
  git:
    url: git://github.com/zegoim/zego-express-flutter-sdk.git
    ref: master

2. 增加实现并保留文件后,在终端执行 flutter pub get。

4 设置权限

以上步骤集成已实现,为保障 SDK 运行成果更佳,须要在利用中依据理论利用须要,设置利用所需权限。步骤如下:

4.1 Android 增加权限

进入“app/src/main”目录,关上“AndroidManifest.xml”文件,增加权限。

<!-- Permissions required by the SDK -->
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
<uses-permission android:name="android.permission.RECORD_AUDIO" />
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.CAMERA" />
<uses-permission android:name="android.permission.BLUETOOTH" />
<uses-permission android:name="android.permission.MODIFY_AUDIO_SETTINGS" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />

<!-- Permissions required by the Demo App -->
<uses-permission android:name="android.permission.READ_PHONE_STATE" />
<uses-permission android:name="android.permission.WAKE_LOCK" />

<uses-feature android:glEsVersion="0x00020000" android:required="true" />
<uses-feature android:name="android.hardware.camera" />
<uses-feature android:name="android.hardware.camera.autofocus" />

因为 Android 6.0 在一些比拟重要的权限上要求必须申请动静权限,不能只通过“AndroidMainfest.xml”文件申请动态权限。请在 Android 原生层参考执行如下代码,其中“requestPermissions”是“Activity”的办法。

String[] permissionNeeded = {
    "android.permission.CAMERA",
    "android.permission.RECORD_AUDIO"};

if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {if (ContextCompat.checkSelfPermission(this, "android.permission.CAMERA") != PackageManager.PERMISSION_GRANTED ||
        ContextCompat.checkSelfPermission(this, "android.permission.RECORD_AUDIO") != PackageManager.PERMISSION_GRANTED) {requestPermissions(permissionNeeded, 101);
    }
}

具体的权限阐明如下:

4.2 iOS 增加权限

关上我的项目,抉择菜单“TARGETS > Info > Custom iOS Target Properties”。

单击“+”按钮,增加摄像头和麦克风权限。

  • Privacy – Camera Usage Description
  • Privacy – Microphone Usage Description

权限增加实现后,如图所示:

5 实现流程

如以下流程图,用户 A 与 B 通过 ZEGO Express SDK 进行视频通话,以用户 A 拉取用户 B 的流为例:

为保障实时音视频的通话质量,推拉流要害流程需依照 API 的正确调用时序进行,残缺时序如下图:

5.1 创立引擎

1. 引入 SDK

在我的项目中引入 SDK。

1import 'package:zego_express_engine/zego_express_engine.dart';

2. 创立引擎

调用 createEngineWithProfile 接口,将申请到的 AppID 传入参数“appID”。

ZegoEngineProfile profile = ZegoEngineProfile(
    appID, // 请通过官网注册获取,格局为:1234567890
    ZegoScenario.General, // 通用场景接入
    enablePlatformView: true);
// 创立引擎
ZegoExpressEngine.createEngineWithProfile(profile);
5.2 登录房间

1. 登录

传入用户 ID 参数“userID”创立 ZegoUser 用户对象后,调用 loginRoom 接口,传入房间 ID 参数“roomID”和用户参数“user”,登录房间。

  • 同一个 AppID 内,需保障“roomID”信息的全局惟一。
  • 同一个 AppID 内,需保障“userID”全局惟一,倡议开发者将其设置成一个有意义的值,可将“userID”与本人业务账号零碎进行关联。
  • “ZegoUser”的构造方法 ZegoUser.id 会将“userName”设为与传的参数“userID”一样。“userID”与“userName”不能为“null”,否则会导致登录房间失败。
// 创立用户对象
ZegoUser user = ZegoUser.id('user1');
// 只有传入“isUserStatusNotify”参数取值为“true”的 ZegoRoomConfig,能力收到 onRoomUserUpdate 回调。ZegoRoomConfig config = ZegoRoomConfig.defaultConfig();
config.isUserStatusNotify = true;
// token 由用户本人的服务端生成,为了更快跑通流程,也能够通过即构控制台获取长期的音视频 token
config.token = "xxxx";
// 开始登录房间
ZegoExpressEngine.instance.loginRoom('room1', user, config: config);

2. 监听登录房间后的事件回调
依据理论利用须要,在登录房间后监听想要关注的事件告诉,比方房间状态更新、用户状态更新、流状态更新等。

  • onRoomStateUpdate:房间状态更新回调。登录房间后,当房间连贯状态产生变更(如呈现房间断开,登录认证失败等状况),SDK 会通过该回调告诉。onRoomUserUpdate:用户状态更新回调。登录房间后,当房间内有用户新增或删除时,SDK 会通过该回调告诉。
  • 只有调用 loginRoom 接口登录房间时传入 ZegoRoomConfig 配置,且“isUserStatusNotify”参数取值为“true”时,用户能力收到 onRoomUserUpdate 回调。
  • onRoomStreamUpdate:流状态更新回调。登录房间后,当房间内有用户新推送或删除音视频流时,SDK 会通过该回调告诉。
// 以下为罕用的房间相干回调
// 房间状态更新回调
ZegoExpressEngine.onRoomStateUpdate = (String roomID, ZegoRoomState state, int errorCode, Map<String, dynamic> extendedData) {// 依据须要实现事件回调};

// 用户状态更新
ZegoExpressEngine.onRoomUserUpdate = (String roomID, ZegoUpdateType updateType, List<ZegoUser> userList) {// 依据须要实现事件回调};

// 流状态更新
ZegoExpressEngine.onRoomStreamUpdate = (String roomID, ZegoUpdateType updateType, List<ZegoStream> streamList) {// 依据须要实现事件回调};
5.3 推流

1. 开始推流
调用 startPublishingStream 接口,传入流 ID 参数“streamID”,向远端用户发送本端的音视频流。
同一个 AppID 内,需保障“streamID”全局惟一。如果同一个 AppID 内,不同用户各推了一条“streamID”雷同的流,会导致后推流的用户推流失败。

// 开始推流
ZegoExpressEngine.instance.startPublishingStream("streamID");

2. 启用本地渲染和预览
如果心愿看到本端的画面,可将画面渲染后,调用 startPreview 接口启动本地预览。
Flutter 的渲染形式有两种:PlatformView 与 TextureRenderer。与 TextureRenderer 相比,PlatformView 占用资源稍高,且稳定性偏低,但随着 Flutter 版本迭代,鲁棒性一直进步。开发者可依据理论状况通过任意一种形式实现渲染。

应用 TextureRenderer 形式渲染

开启 TextureRenderer 后,在销毁引擎之前,只能应用 TextureRenderer 而不能应用 PlatformView。
(1)创立预览用的“TextureRenderer”(外接纹理)。

void createPreviewRenderer() {ZegoExpressEngine.instance.createTextureRenderer(widget.screenWidthPx, widget.screenHeightPx).then((textureID) {

        _previewViewID = textureID;

        setState(() {
            // Create a Texture Widget
            Widget previewViewWidget = Texture(textureId: textureID);
            // 将此 Widget 退出到页面的渲染树中以显示预览画面
            _previewViewWidget = previewViewWidget;
        });

        // Start preview using texture renderer
        _startPreview(textureID);
    });
}

(2)应用 TextureRenderer 的“textureID”作为“viewID”创立一个 ZegoCanvas 对象,开始预览。
void _startPreview(int viewID) {

  // Set the preview canvas
    ZegoCanvas previewCanvas = ZegoCanvas.view(viewID);

    // Start preview
    ZegoExpressEngine.instance.startPreview(canvas: previewCanvas);
}

3. 监听推流后的事件回调

依据理论利用须要,在推流后监听想要关注的事件告诉,比方推流状态更新等。
onPublisherStateUpdate:推流状态更新回调。调用推流接口胜利后,当推流状态产生变更(如呈现网络中断导致推流异样等状况),SDK 在重试推流的同时,会通过该回调告诉。

// 罕用的推流相干回调
// 推流状态更新回调
ZegoExpressEngine.onPublisherStateUpdate = (String streamID, ZegoPublisherState state, int errorCode, Map<String, dynamic> extendedData) {// 依据须要实现事件回调};
5.4 拉流

调用 startPlayingStream 接口,依据传入的流 ID 参数“streamID”,拉取远端推送的音视频流,并依据须要渲染拉流画面。

  • 若仅需拉音频流,不须要显示拉流画面,可间接调用 startPlayingStream 接口。

ZegoExpressEngine.instance.startPlayingStream(streamID);

  • 若须要在拉流的同时,渲染拉流画面,Flutter 的渲染形式有两种:PlatformView 与 TextureRenderer。与 TextureRenderer 相比,PlatformView 占用资源稍高,且稳定性偏低,但随着 Flutter 版本迭代,鲁棒性一直进步。开发者可依据理论状况通过任意一种形式实现渲染。

应用 TextureRenderer 形式渲染
(1)创立预览用的“TextureRenderer”(外接纹理)。

ZegoExpressEngine.instance.createTextureRenderer(width.toInt(), height.toInt()).then((viewID) {
    _playViewID = viewID;
    // 将失去的 Widget 退出到页面的渲染树中以显示拉流画面
    setState(() => _playViewWidget = Texture(textureId: viewID));
    _startPlayingStream(viewID, streamID);
});

(2)应用 TextureRenderer 的“textureID”作为“viewID”创立一个 ZegoCanvas 对象,开始拉流并渲染拉流画面。

void _startPlayingStream(int viewID, String streamID) {ZegoCanvas canvas = ZegoCanvas.view(viewID);
    ZegoExpressEngine.instance.startPlayingStream(streamID, canvas: canvas);
}
5.5 体验实时音视频性能

在真机中运行我的项目,运行胜利后,能够看到本端视频画面。
为不便体验,ZEGO 提供了一个 Web 端调试示例,在该页面下,输出雷同的 AppID、RoomID、Server 地址和 Token,即可退出同一房间与真机设备互通。当胜利开始音视频通话时,能够听到远端的音频,看到远端的视频画面。

5.6 进行推拉流

1. 进行推流 / 预览 / 渲染
调用 stopPublishingStream 接口进行向远端用户发送本端的音视频流。

// 进行推流
ZegoExpressEngine.instance.stopPublishingStream();

如果启用了本地预览,调用 stopPreview 接口进行预览。

// 进行预览
ZegoExpressEngine.instance.stopPreview();

如果预览时创立了 TextureRenderer,须要调用 destroyTextureRenderer 接口销毁 TextureRenderer。

// _previewViewID 为调用 createTextureRenderer 时失去的 viewID
ZegoExpressEngine.instance.destroyTextureRenderer(_previewViewID);

如果预览时创立了 PlatformView,须要调用 destroyPlatformView 接口销毁 PlatformView。

// _previewViewID 为调用 [createPlatformView] 时失去的 viewID
ZegoExpressEngine.instance.destroyPlatformView(_previewViewID);

2. 进行拉流 / 渲染

调用 stopPlayingStream 接口进行拉取远端推送的音视频流。

// 进行拉流
ZegoExpressEngine.instance.stopPlayingStream(streamID, canvas: _playCanvas);

如果拉流时创立了 TextureRenderer,须要调用 destroyTextureRenderer 接口销毁 TextureRenderer。

// _playViewID 为调用 [createTextureRenderer] 时失去的 viewID
ZegoExpressEngine.instance.destroyTextureRenderer(_playViewID);

如果拉流时创立了 PlatformView,须要调用 destroyPlatformView 接口销毁 PlatformView。

// _playViewID 为调用 [createPlatformView] 时失去的 viewID
ZegoExpressEngine.instance.destroyPlatformView(_playViewID);
5.7 退出房间

调用 logoutRoom 接口退出房间。

// 退出房间
ZegoExpressEngine.instance.logoutRoom('room1');
5.8 销毁引擎

调用 destroyEngine 接口销毁引擎,用于开释 SDK 应用的资源。

// 销毁引擎
ZegoExpressEngine.destroyEngine();

结尾

祝贺,你曾经通过 ZEGO Flutter SDK 实现了本人的实时音视频通话利用,Flutter 为利用开发带来了变革,带着学习交换的态度,心愿对于想要学习利用 Flutter 的同学有所帮忙。

获取 Demo

获取本文的 Demo、开发文档、技术支持。
获取 SDK 的商务活动、热门产品。
注册即构 ZEGO 开发者帐号,疾速开始。

退出移动版