From 95d180c9f47721dac90318e3a7a88c24e6f05c9e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=B6=85=E6=82=9F=E7=A9=BA?= <39251474@163.com> Date: Wed, 10 Jul 2019 11:21:17 +0800 Subject: [PATCH 1/2] =?UTF-8?q?=E7=AE=80=E5=8C=96=E4=BA=86=E5=8E=9F?= =?UTF-8?q?=E7=94=9F=E6=B8=B2=E6=9F=93=E7=AA=97=E5=8F=A3=E7=9A=84=E5=88=9B?= =?UTF-8?q?=E5=BB=BA=E6=8E=A5=E5=8F=A3=EF=BC=8C=E5=A2=9E=E5=8A=A0=E4=BA=86?= =?UTF-8?q?=E4=B8=80=E4=B8=AA=E5=AE=9E=E7=94=A8=E6=B8=B2=E6=9F=93=E7=AA=97?= =?UTF-8?q?=E5=8F=A3=E6=8E=A7=E4=BB=B6?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- example/lib/main.dart | 73 +++++++++++++++++-------- example/pubspec.yaml | 2 +- lib/agora_rtc_engine.dart | 22 ++++---- lib/src/agora_render_widget.dart | 94 ++++++++++++++++++++++++++++++++ 4 files changed, 155 insertions(+), 36 deletions(-) create mode 100644 lib/src/agora_render_widget.dart diff --git a/example/lib/main.dart b/example/lib/main.dart index f607acb6e..f190f7e0d 100644 --- a/example/lib/main.dart +++ b/example/lib/main.dart @@ -16,15 +16,18 @@ class _MyAppState extends State { static final _sessions = List(); + /// 远程用户列表 + final _remoteUsers = List(); + @override void initState() { super.initState(); _initAgoraRtcEngine(); _addAgoraEventHandlers(); - _addRenderView(0, (viewId) { - AgoraRtcEngine.setupLocalVideo(viewId, VideoRenderMode.Hidden); - }); +// _addRenderView(0, (viewId) { +// AgoraRtcEngine.setupLocalVideo(viewId, VideoRenderMode.Hidden); +// }); } @override @@ -53,7 +56,7 @@ class _MyAppState extends State { Future _initAgoraRtcEngine() async { AgoraRtcEngine.create('YOUR APP ID'); - + AgoraRtcEngine.enableVideo(); AgoraRtcEngine.setChannelProfile(ChannelProfile.Communication); @@ -81,9 +84,10 @@ class _MyAppState extends State { setState(() { String info = 'userJoined: ' + uid.toString(); _infoStrings.add(info); - _addRenderView(uid, (viewId) { - AgoraRtcEngine.setupRemoteVideo(viewId, VideoRenderMode.Hidden, uid); - }); +// _addRenderView(uid, (viewId) { +// AgoraRtcEngine.setupRemoteVideo(viewId, VideoRenderMode.Hidden, uid); +// }); + _remoteUsers.add(uid); }); }; @@ -91,7 +95,8 @@ class _MyAppState extends State { setState(() { String info = 'userOffline: ' + uid.toString(); _infoStrings.add(info); - _removeRenderView(uid); +// _removeRenderView(uid); + _remoteUsers.remove(uid); }); }; @@ -124,26 +129,46 @@ class _MyAppState extends State { } Widget _viewRows() { - List views = _getRenderViews(); - if (views.length > 0) { - List expandeViews = views - .map((widget) => Expanded(child: Container(child: widget))) - .toList(); - return Row(children: expandeViews); - } else { - return null; +// List views = _getRenderViews(); +// if (views.length > 0) { +// List expandeViews = views +// .map((widget) => Expanded(child: Container(child: widget))) +// .toList(); +// return Row(children: expandeViews); +// } else { +// return null; +// } + + return Row( + children: [ + for (final widget in _renderWidget) + Expanded( + child: Container( + child: widget, + ), + ) + ], + ); + } + + /// 获取渲染窗口列表 + Iterable get _renderWidget sync* { + yield AgoraRenderWidget(0, self: true); + + for (final uid in _remoteUsers) { + yield AgoraRenderWidget(uid); } } void _addRenderView(int uid, Function(int viewId) finished) { - Widget view = AgoraRtcEngine.createNativeView(uid, (viewId) { - _getVideoSession(uid).viewId = viewId; - if (finished != null) { - finished(viewId); - } - }); - VideoSession session = VideoSession(uid, view); - _sessions.add(session); +// Widget view = AgoraRtcEngine.createNativeView(uid, (viewId) { +// _getVideoSession(uid).viewId = viewId; +// if (finished != null) { +// finished(viewId); +// } +// }); +// VideoSession session = VideoSession(uid, view); +// _sessions.add(session); } void _removeRenderView(int uid) { diff --git a/example/pubspec.yaml b/example/pubspec.yaml index bbade7083..cc00a41a9 100644 --- a/example/pubspec.yaml +++ b/example/pubspec.yaml @@ -3,7 +3,7 @@ description: Demonstrates how to use the agora_rtc_engine plugin. publish_to: 'none' environment: - sdk: ">=2.1.0 <3.0.0" + sdk: ">=2.2.2 <3.0.0" dependencies: flutter: diff --git a/lib/agora_rtc_engine.dart b/lib/agora_rtc_engine.dart index 640164ed9..b01c97759 100644 --- a/lib/agora_rtc_engine.dart +++ b/lib/agora_rtc_engine.dart @@ -3,6 +3,8 @@ import 'dart:io'; import 'package:flutter/material.dart'; import 'package:flutter/services.dart'; +export 'src/agora_render_widget.dart'; + class AgoraRtcEngine { static const MethodChannel _channel = const MethodChannel('agora_rtc_engine'); @@ -215,7 +217,7 @@ class AgoraRtcEngine { /// Only users with the same App ID can join the same channel and call each other. static Future create(String appid) async { _addMethodCallHandler(); - return await _channel.invokeMethod('create', {'appId': appid}); + await _channel.invokeMethod('create', {'appId': appid}); } /// Destroys the RtcEngine instance and releases all resources used by the Agora SDK. @@ -224,7 +226,7 @@ class AgoraRtcEngine { /// Once the app calls destroy to destroy the created RtcEngine instance, you cannot use any method or callback in the SDK. static Future destroy() async { _removeMethodCallHandler(); - return await _channel.invokeMethod('destroy'); + await _channel.invokeMethod('destroy'); } /// Sets the channel profile. @@ -234,8 +236,7 @@ class AgoraRtcEngine { /// Before calling this method to set a new channel profile, [destroy] the current RtcEngine and [create] a new RtcEngine first. /// Call this method before [joinChannel], you cannot configure the channel profile when the channel is in use. static Future setChannelProfile(ChannelProfile profile) async { - return await _channel - .invokeMethod('setChannelProfile', {'profile': profile.index}); + await _channel.invokeMethod('setChannelProfile', {'profile': profile.index}); } /// Sets the role of a user (Live Broadcast only). @@ -244,7 +245,7 @@ class AgoraRtcEngine { /// This method can be used to switch the user role after a user joins a channel. static Future setClientRole(ClientRole role) async { int roleValue = _intFromClientRole(role); - return await _channel.invokeMethod('setClientRole', {'role': roleValue}); + await _channel.invokeMethod('setClientRole', {'role': roleValue}); } /// Allows a user to join a channel. @@ -271,15 +272,14 @@ class AgoraRtcEngine { /// /// The app should retrieve a new token from the server and call this method to renew it. Failure to do so results in the SDK disconnecting from the server. static Future renewToken(String token) async { - return await _channel.invokeMethod('renewToken', {'token': token}); + await _channel.invokeMethod('renewToken', {'token': token}); } /// Enables interoperability with the Agora Web SDK (Live Broadcast only). /// /// Use this method when the channel profile is Live Broadcast. Interoperability with the Agora Web SDK is enabled by default when the channel profile is Communication. static Future enableWebSdkInteroperability(bool enabled) async { - return await _channel - .invokeMethod('enableWebSdkInteroperability', {'enabled': enabled}); + await _channel.invokeMethod('enableWebSdkInteroperability', {'enabled': enabled}); } /// Gets the connection state of the SDK. @@ -423,10 +423,10 @@ class AgoraRtcEngine { /// Creates the video renderer Widget. /// /// The Widget is identified by viewId, the operation and layout of the Widget are managed by the app. - static Widget createNativeView(int uid, Function(int viewId) created) { + static Widget createNativeView(Function(int viewId) created, {Key key}) { if (Platform.isIOS) { return UiKitView( - key: new ObjectKey(uid.toString()), + key: key, viewType: 'AgoraRendererView', onPlatformViewCreated: (viewId) { if (created != null) { @@ -436,7 +436,7 @@ class AgoraRtcEngine { ); } else { return AndroidView( - key: new ObjectKey(uid.toString()), + key: key, viewType: 'AgoraRendererView', onPlatformViewCreated: (viewId) { if (created != null) { diff --git a/lib/src/agora_render_widget.dart b/lib/src/agora_render_widget.dart new file mode 100644 index 000000000..d630c39de --- /dev/null +++ b/lib/src/agora_render_widget.dart @@ -0,0 +1,94 @@ +// Created by 超悟空 on 2019/7/10. +// Version 1.0 2019/7/10 +// Since 1.0 2019/7/10 + +import 'package:agora_rtc_engine/agora_rtc_engine.dart'; +import 'package:flutter/material.dart'; + +/// 简单渲染窗口控件 +/// +/// 自动创建和销毁内部原生控件,自动绑定用户 +class AgoraRenderWidget extends StatefulWidget { + /// 绑定的uid + final int uid; + + /// 是否是自己 + /// + /// 当为true时使用[AgoraRtcEngine.setupLocalVideo]绑定视频窗口, + /// 否则使用[AgoraRtcEngine.setupRemoteVideo]绑定视频窗口 + final bool self; + + /// 窗口填充模式 + final VideoRenderMode mode; + + AgoraRenderWidget( + this.uid, { + this.mode = VideoRenderMode.Hidden, + this.self = false, + }) : assert(uid != null), + assert(mode != null), + assert(self != null); + + @override + State createState() => _AgoraRenderWidgetState(); +} + +class _AgoraRenderWidgetState extends State { + /// 原生组件 + Widget _nativeView; + + /// 原生组件id + int _viewId; + + @override + void initState() { + super.initState(); + _nativeView = AgoraRtcEngine.createNativeView((viewId) { + _viewId = viewId; + _bindView(); + }); + } + + @override + void dispose() { + AgoraRtcEngine.removeNativeView(_viewId); + super.dispose(); + } + + @override + void didUpdateWidget(AgoraRenderWidget oldWidget) { + super.didUpdateWidget(oldWidget); + + if ((widget.uid != oldWidget.uid || widget.self != oldWidget.self) && + _viewId != null) { + _bindView(); + return; + } + + if (widget.mode != oldWidget.mode) { + _changeMode(); + return; + } + } + + /// 绑定用户和原生控件 + void _bindView() { + if (widget.self) { + AgoraRtcEngine.setupLocalVideo(_viewId, widget.mode); + } else { + AgoraRtcEngine.setupRemoteVideo(_viewId, widget.mode, widget.uid); + } + } + + /// 改变缩放模式 + void _changeMode() { + if (widget.self) { + AgoraRtcEngine.setLocalRenderMode(widget.mode); + } else { + AgoraRtcEngine.setRemoteRenderMode(widget.uid, widget.mode); + } + } + + @override + Widget build(BuildContext context) => _nativeView; +} From bf46f0ef78bf0f60ecc0c74fc4e912d1568e7b84 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=B6=85=E6=82=9F=E7=A9=BA?= <39251474@163.com> Date: Wed, 10 Jul 2019 11:42:08 +0800 Subject: [PATCH 2/2] get the rtc engine method --- .../java/io/agora/agorartcengine/AgoraRtcEnginePlugin.java | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/android/src/main/java/io/agora/agorartcengine/AgoraRtcEnginePlugin.java b/android/src/main/java/io/agora/agorartcengine/AgoraRtcEnginePlugin.java index c8d1d580f..bc5444694 100644 --- a/android/src/main/java/io/agora/agorartcengine/AgoraRtcEnginePlugin.java +++ b/android/src/main/java/io/agora/agorartcengine/AgoraRtcEnginePlugin.java @@ -28,7 +28,7 @@ public class AgoraRtcEnginePlugin implements MethodCallHandler { private final Registrar mRegistrar; private final MethodChannel mMethodChannel; - private RtcEngine mRtcEngine; + private static RtcEngine mRtcEngine; private HashMap mRendererViews; private Handler mEventHandler = new Handler(Looper.getMainLooper()); @@ -44,6 +44,10 @@ private SurfaceView getView(int id) { return mRendererViews.get("" + id); } + public static RtcEngine getRtcEngine() { + return mRtcEngine; + } + /** * Plugin registration. */