Skip to content

Commit

Permalink
Merge pull request #18 from cwkProject/master
Browse files Browse the repository at this point in the history
简化了原生渲染窗口的创建接口,增加了一个实用渲染窗口控件
  • Loading branch information
Matrixbirds authored Aug 1, 2019
2 parents d6f2203 + bf46f0e commit c130c6d
Show file tree
Hide file tree
Showing 5 changed files with 160 additions and 37 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -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<String, SurfaceView> mRendererViews;
private Handler mEventHandler = new Handler(Looper.getMainLooper());

Expand All @@ -44,6 +44,10 @@ private SurfaceView getView(int id) {
return mRendererViews.get("" + id);
}

public static RtcEngine getRtcEngine() {
return mRtcEngine;
}

/**
* Plugin registration.
*/
Expand Down
73 changes: 49 additions & 24 deletions example/lib/main.dart
Original file line number Diff line number Diff line change
Expand Up @@ -16,15 +16,18 @@ class _MyAppState extends State<MyApp> {

static final _sessions = List<VideoSession>();

/// 远程用户列表
final _remoteUsers = List<int>();

@override
void initState() {
super.initState();

_initAgoraRtcEngine();
_addAgoraEventHandlers();
_addRenderView(0, (viewId) {
AgoraRtcEngine.setupLocalVideo(viewId, VideoRenderMode.Hidden);
});
// _addRenderView(0, (viewId) {
// AgoraRtcEngine.setupLocalVideo(viewId, VideoRenderMode.Hidden);
// });
}

@override
Expand Down Expand Up @@ -53,7 +56,7 @@ class _MyAppState extends State<MyApp> {

Future<void> _initAgoraRtcEngine() async {
AgoraRtcEngine.create('YOUR APP ID');

AgoraRtcEngine.enableVideo();
AgoraRtcEngine.setChannelProfile(ChannelProfile.Communication);

Expand Down Expand Up @@ -81,17 +84,19 @@ class _MyAppState extends State<MyApp> {
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);
});
};

AgoraRtcEngine.onUserOffline = (int uid, int reason) {
setState(() {
String info = 'userOffline: ' + uid.toString();
_infoStrings.add(info);
_removeRenderView(uid);
// _removeRenderView(uid);
_remoteUsers.remove(uid);
});
};

Expand Down Expand Up @@ -124,26 +129,46 @@ class _MyAppState extends State<MyApp> {
}

Widget _viewRows() {
List<Widget> views = _getRenderViews();
if (views.length > 0) {
List<Widget> expandeViews = views
.map((widget) => Expanded(child: Container(child: widget)))
.toList();
return Row(children: expandeViews);
} else {
return null;
// List<Widget> views = _getRenderViews();
// if (views.length > 0) {
// List<Widget> expandeViews = views
// .map((widget) => Expanded(child: Container(child: widget)))
// .toList();
// return Row(children: expandeViews);
// } else {
// return null;
// }

return Row(
children: <Widget>[
for (final widget in _renderWidget)
Expanded(
child: Container(
child: widget,
),
)
],
);
}

/// 获取渲染窗口列表
Iterable<Widget> 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) {
Expand Down
2 changes: 1 addition & 1 deletion example/pubspec.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -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:
Expand Down
22 changes: 11 additions & 11 deletions lib/agora_rtc_engine.dart
Original file line number Diff line number Diff line change
Expand Up @@ -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');

Expand Down Expand Up @@ -215,7 +217,7 @@ class AgoraRtcEngine {
/// Only users with the same App ID can join the same channel and call each other.
static Future<void> 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.
Expand All @@ -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<void> destroy() async {
_removeMethodCallHandler();
return await _channel.invokeMethod('destroy');
await _channel.invokeMethod('destroy');
}

/// Sets the channel profile.
Expand All @@ -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<void> 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).
Expand All @@ -244,7 +245,7 @@ class AgoraRtcEngine {
/// This method can be used to switch the user role after a user joins a channel.
static Future<void> 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.
Expand All @@ -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<void> 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<void> enableWebSdkInteroperability(bool enabled) async {
return await _channel
.invokeMethod('enableWebSdkInteroperability', {'enabled': enabled});
await _channel.invokeMethod('enableWebSdkInteroperability', {'enabled': enabled});
}

/// Gets the connection state of the SDK.
Expand Down Expand Up @@ -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) {
Expand All @@ -436,7 +436,7 @@ class AgoraRtcEngine {
);
} else {
return AndroidView(
key: new ObjectKey(uid.toString()),
key: key,
viewType: 'AgoraRendererView',
onPlatformViewCreated: (viewId) {
if (created != null) {
Expand Down
94 changes: 94 additions & 0 deletions lib/src/agora_render_widget.dart
Original file line number Diff line number Diff line change
@@ -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<StatefulWidget> createState() => _AgoraRenderWidgetState();
}

class _AgoraRenderWidgetState extends State<AgoraRenderWidget> {
/// 原生组件
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;
}

0 comments on commit c130c6d

Please sign in to comment.