共计 8566 个字符,预计需要花费 22 分钟才能阅读完成。
之前的文章公布了 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 开发者帐号,疾速开始。