remote_video_views_widget.dart 3.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129
  1. import 'package:agora_rtc_engine/agora_rtc_engine.dart';
  2. import 'log_sink.dart';
  3. import 'package:flutter/material.dart';
  4. mixin KeepRemoteVideoViewsMixin<T extends StatefulWidget> on State<T> {
  5. final GlobalKey _keepRemoteVideoViewsKey = GlobalKey();
  6. GlobalKey get keepRemoteVideoViewsKey => _keepRemoteVideoViewsKey;
  7. }
  8. class RemoteVideoViewsWidget extends StatefulWidget {
  9. const RemoteVideoViewsWidget(
  10. {Key? key,
  11. required this.rtcEngine,
  12. required this.channelId,
  13. this.connectionUid})
  14. : super(key: key);
  15. final RtcEngine rtcEngine;
  16. final String channelId;
  17. final int? connectionUid;
  18. @override
  19. State<RemoteVideoViewsWidget> createState() => _RemoteVideoViewsWidgetState();
  20. }
  21. class _RemoteVideoViewsWidgetState extends State<RemoteVideoViewsWidget> {
  22. late final RtcEngineEventHandler _eventHandler;
  23. final Set<RtcConnection> _localRtcConnection = {};
  24. final Map<int, RtcConnection> _remoteUidsMap = {};
  25. @override
  26. void initState() {
  27. super.initState();
  28. _init();
  29. }
  30. void _init() {
  31. _eventHandler = RtcEngineEventHandler(
  32. onJoinChannelSuccess: (connection, elapsed) {
  33. _localRtcConnection.add(connection);
  34. },
  35. onLeaveChannel: (RtcConnection connection, RtcStats stats) {
  36. _localRtcConnection
  37. .removeWhere((e) => e.localUid == connection.localUid);
  38. _remoteUidsMap
  39. .removeWhere((key, value) => value.localUid == connection.localUid);
  40. },
  41. onUserJoined: (connection, remoteUid, elapsed) {
  42. logSink.log(
  43. '[onUserJoined] connection: ${connection.toJson()}, remoteUid: $remoteUid, elapsed: $elapsed');
  44. setState(() {
  45. if (!_localRtcConnection.any((e) => e.localUid == remoteUid)) {
  46. _remoteUidsMap.putIfAbsent(remoteUid, () => connection);
  47. }
  48. });
  49. },
  50. onUserOffline: (RtcConnection connection, int remoteUid,
  51. UserOfflineReasonType reason) {
  52. logSink.log(
  53. '[onUserOffline] connection: ${connection.toJson()}, remoteUid: $remoteUid');
  54. setState(() {
  55. _remoteUidsMap.remove(remoteUid);
  56. });
  57. },
  58. );
  59. widget.rtcEngine.registerEventHandler(_eventHandler);
  60. }
  61. @override
  62. void dispose() {
  63. widget.rtcEngine.unregisterEventHandler(_eventHandler);
  64. super.dispose();
  65. }
  66. @override
  67. Widget build(BuildContext context) {
  68. final widgets = <Widget>[];
  69. debugPrint('_remoteUidsMap: $_remoteUidsMap');
  70. _remoteUidsMap.forEach((key, value) {
  71. widgets.add(
  72. SizedBox(
  73. width: 150,
  74. height: 150,
  75. child: Stack(
  76. children: [
  77. AgoraVideoView(
  78. controller: VideoViewController.remote(
  79. rtcEngine: widget.rtcEngine,
  80. canvas: VideoCanvas(uid: key),
  81. connection: RtcConnection(
  82. channelId: widget.channelId,
  83. localUid: widget.connectionUid),
  84. ),
  85. ),
  86. Column(
  87. mainAxisAlignment: MainAxisAlignment.start,
  88. crossAxisAlignment: CrossAxisAlignment.start,
  89. mainAxisSize: MainAxisSize.min,
  90. children: [
  91. Text(
  92. widget.connectionUid != null
  93. ? 'localuid: ${widget.connectionUid}'
  94. : '',
  95. style: const TextStyle(color: Colors.white, fontSize: 10),
  96. ),
  97. Text(
  98. 'remoteuid: $key',
  99. style: const TextStyle(color: Colors.white, fontSize: 10),
  100. ),
  101. ],
  102. )
  103. ],
  104. ),
  105. ),
  106. );
  107. });
  108. return SingleChildScrollView(
  109. scrollDirection: Axis.horizontal,
  110. child: Row(
  111. mainAxisAlignment: MainAxisAlignment.start,
  112. crossAxisAlignment: CrossAxisAlignment.start,
  113. children: widgets,
  114. ),
  115. );
  116. }
  117. }