Skip to content

Commit

Permalink
fix: fix setupRemoteVideoEx not call correctly (#909)
Browse files Browse the repository at this point in the history
* fix: fix not call setupRemoteVideoEx when VideoViewControllerBaseMixin.disposeRender
  • Loading branch information
littleGnAl committed Feb 27, 2023
1 parent ab478ae commit ac5900c
Show file tree
Hide file tree
Showing 5 changed files with 181 additions and 5 deletions.
4 changes: 2 additions & 2 deletions lib/src/impl/agora_rtc_engine_impl.dart
Expand Up @@ -207,10 +207,10 @@ class RtcEngineImpl extends rtc_engine_ex_binding.RtcEngineExImpl
@internal
final MethodChannel engineMethodChannel = const MethodChannel('agora_rtc_ng');

static RtcEngineEx create() {
static RtcEngineEx create({IrisMethodChannel? irisMethodChannel}) {
if (_instance != null) return _instance!;

_instance = RtcEngineImpl._(IrisMethodChannel());
_instance = RtcEngineImpl._(irisMethodChannel ?? IrisMethodChannel());

return _instance!;
}
Expand Down
7 changes: 6 additions & 1 deletion lib/src/impl/video_view_controller_impl.dart
Expand Up @@ -92,7 +92,12 @@ mixin VideoViewControllerBaseMixin implements VideoViewControllerBase {
mediaPlayerId: canvas.mediaPlayerId,
);
if (canvas.uid != 0) {
await rtcEngine.setupRemoteVideo(videoCanvas);
if (connection != null && rtcEngine is RtcEngineEx) {
await (rtcEngine as RtcEngineEx)
.setupRemoteVideoEx(canvas: videoCanvas, connection: connection!);
} else {
await rtcEngine.setupRemoteVideo(videoCanvas);
}
} else {
await rtcEngine.setupLocalVideo(videoCanvas);
}
Expand Down
4 changes: 3 additions & 1 deletion lib/src/render/video_view_controller.dart
Expand Up @@ -71,7 +71,9 @@ class VideoViewController
required this.connection,
this.useFlutterTexture = false,
this.useAndroidSurfaceView = false})
: assert(connection.channelId != null);
: assert(canvas.uid != null && canvas.uid != 0,
'Remote uid can not be null or 0'),
assert(connection.channelId != null);

@override
final RtcEngine rtcEngine;
Expand Down
@@ -0,0 +1,35 @@
import 'package:flutter/foundation.dart';
import 'package:iris_method_channel/iris_method_channel.dart';

class FakeIrisMethodChannel extends IrisMethodChannel {
final List<IrisMethodCall> methodCallQueue = [];

@override
Future<void> initilize(NativeBindingsProvider provider) async {}

@override
Future<CallApiResult> invokeMethod(IrisMethodCall methodCall) async {
methodCallQueue.add(methodCall);
return CallApiResult(data: {'result': 0}, irisReturnCode: 0);
}

@override
int getNativeHandle() {
return 100;
}

@override
VoidCallback addHotRestartListener(HotRestartListener listener) {
return () {};
}

@override
void removeHotRestartListener(HotRestartListener listener) {}

@override
Future<void> dispose() async {}

void reset() {
methodCallQueue.clear();
}
}
@@ -1,18 +1,24 @@
import 'dart:convert';
import 'dart:io';

import 'package:agora_rtc_engine/agora_rtc_engine.dart';
import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
import 'package:flutter_test/flutter_test.dart';
import 'package:agora_rtc_engine/src/impl/agora_rtc_engine_impl.dart';
import '../fake/fake_iris_method_channel.dart';

class _RenderViewWidget extends StatefulWidget {
const _RenderViewWidget({
Key? key,
required this.builder,
required this.rtcEngine,
}) : super(key: key);

final Function(BuildContext context, RtcEngine engine) builder;

final RtcEngine rtcEngine;

@override
State<_RenderViewWidget> createState() => _RenderViewWidgetState();
}
Expand Down Expand Up @@ -41,7 +47,7 @@ class _RenderViewWidgetState extends State<_RenderViewWidget> {
String engineAppId = const String.fromEnvironment('TEST_APP_ID',
defaultValue: '<YOUR_APP_ID>');

_engine = createAgoraRtcEngine();
_engine = widget.rtcEngine;
await _engine.initialize(RtcEngineContext(
appId: engineAppId,
areaCode: AreaCode.areaCodeGlob.value(),
Expand Down Expand Up @@ -75,7 +81,12 @@ void testCases() {
testWidgets(
'Show local AgoraVideoView after RtcEngine.initialize',
(WidgetTester tester) async {
final irisMethodChannel = FakeIrisMethodChannel();
final rtcEngine =
RtcEngineImpl.create(irisMethodChannel: irisMethodChannel);

await tester.pumpWidget(_RenderViewWidget(
rtcEngine: rtcEngine,
builder: (context, engine) {
return SizedBox(
height: 100,
Expand All @@ -90,6 +101,8 @@ void testCases() {
},
));

await tester.pumpAndSettle(const Duration(milliseconds: 5000));
// pumpAndSettle again to ensure the `AgoraVideoView` shown
await tester.pumpAndSettle(const Duration(milliseconds: 5000));

if (defaultTargetPlatform == TargetPlatform.android) {
Expand All @@ -100,11 +113,132 @@ void testCases() {
expect(find.byType(UiKitView), findsOneWidget);
}

final setupLocalVideoCalls = irisMethodChannel.methodCallQueue
.where((e) => e.funcName == 'RtcEngine_setupLocalVideo')
.toList();

final jsonMap2 = jsonDecode(setupLocalVideoCalls[0].params);
expect(jsonMap2['canvas']['view'] != 0, isTrue);

await tester.pumpWidget(Container());
await tester.pumpAndSettle(const Duration(milliseconds: 5000));

expect(find.byType(AgoraVideoView), findsNothing);
},
skip: !(Platform.isAndroid || Platform.isIOS),
);

testWidgets(
'Switch local/remote AgoraVideoView with RtcConnection',
(WidgetTester tester) async {
final irisMethodChannel = FakeIrisMethodChannel();
final rtcEngine =
RtcEngineImpl.create(irisMethodChannel: irisMethodChannel);

await tester.pumpWidget(_RenderViewWidget(
rtcEngine: rtcEngine,
builder: (context, engine) {
return Column(
children: [
SizedBox(
height: 100,
width: 100,
child: AgoraVideoView(
controller: VideoViewController(
rtcEngine: engine,
canvas: const VideoCanvas(uid: 0),
),
),
),
SizedBox(
height: 100,
width: 100,
child: AgoraVideoView(
controller: VideoViewController.remote(
rtcEngine: engine,
canvas: const VideoCanvas(uid: 1000),
connection: const RtcConnection(
channelId: 'switch_video_view',
localUid: 1000,
),
),
),
)
],
);
},
));

await tester.pumpAndSettle(const Duration(milliseconds: 5000));
// pumpAndSettle again to ensure the `AgoraVideoView` shown
await tester.pumpAndSettle(const Duration(milliseconds: 5000));

if (defaultTargetPlatform == TargetPlatform.android) {
expect(find.byType(AndroidView), findsNWidgets(2));
}

if (defaultTargetPlatform == TargetPlatform.iOS) {
expect(find.byType(UiKitView), findsNWidgets(2));
}

// Clear the methodCall records
irisMethodChannel.reset();

await tester.pumpWidget(_RenderViewWidget(
rtcEngine: rtcEngine,
builder: (context, engine) {
return Column(
children: [
SizedBox(
height: 100,
width: 100,
child: AgoraVideoView(
controller: VideoViewController.remote(
rtcEngine: engine,
canvas: const VideoCanvas(uid: 1000),
connection: const RtcConnection(
channelId: 'switch_video_view',
localUid: 1000,
),
),
),
),
SizedBox(
height: 100,
width: 100,
child: AgoraVideoView(
controller: VideoViewController(
rtcEngine: engine,
canvas: const VideoCanvas(uid: 0),
),
),
)
],
);
},
));

await tester.pumpAndSettle(const Duration(milliseconds: 5000));
if (defaultTargetPlatform == TargetPlatform.android) {
expect(find.byType(AndroidView), findsNWidgets(2));
}
if (defaultTargetPlatform == TargetPlatform.iOS) {
expect(find.byType(UiKitView), findsNWidgets(2));
}

final setupRemoteVideoExCalls = irisMethodChannel.methodCallQueue
.where((e) => e.funcName == 'RtcEngineEx_setupRemoteVideoEx')
.toList();

final jsonMap1 = jsonDecode(setupRemoteVideoExCalls[0].params);
expect(jsonMap1['canvas']['view'] == 0, isTrue);

final jsonMap2 = jsonDecode(setupRemoteVideoExCalls[1].params);
expect(jsonMap2['canvas']['view'] != 0, isTrue);

await tester.pumpWidget(Container());
await tester.pumpAndSettle(const Duration(milliseconds: 5000));
},
skip: !(Platform.isAndroid || Platform.isIOS),
);
}

0 comments on commit ac5900c

Please sign in to comment.