Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

简化了原生渲染窗口的创建接口,增加了一个实用渲染窗口控件 #18

Merged
merged 2 commits into from
Aug 1, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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;
}