123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193 |
- import 'dart:developer';
- import 'package:agora_rtc_engine/rtc_engine.dart';
- import 'package:agora_rtc_engine/rtc_local_view.dart' as RtcLocalView;
- import 'package:agora_rtc_engine/rtc_remote_view.dart' as RtcRemoteView;
- import 'package:agora_rtc_engine_example/config/agora.config.dart' as config;
- import 'package:flutter/cupertino.dart';
- import 'package:flutter/foundation.dart';
- import 'package:flutter/material.dart';
- import 'package:permission_handler/permission_handler.dart';
- /// MediaChannelRelay Example
- class MediaChannelRelay extends StatefulWidget {
- @override
- State<StatefulWidget> createState() => _State();
- }
- class _State extends State<MediaChannelRelay> {
- late final RtcEngine _engine;
- bool isJoined = false;
- int? remoteUid;
- bool isRelaying = false;
- @override
- void initState() {
- super.initState();
- }
- @override
- void dispose() {
- super.dispose();
- _engine.destroy();
- }
- _initEngine() async {
- if (defaultTargetPlatform == TargetPlatform.android) {
- await Permission.microphone.request();
- }
- _engine = await RtcEngine.createWithContext(RtcEngineContext(config.appId));
- this._addListener();
- // enable video module and set up video encoding configs
- await _engine.enableVideo();
- // make this room live broadcasting room
- await _engine.setChannelProfile(ChannelProfile.LiveBroadcasting);
- await _engine.setClientRole(ClientRole.Broadcaster);
- // Set audio route to speaker
- await _engine.setDefaultAudioRoutetoSpeakerphone(true);
- // start joining channel
- // 1. Users can only see each other after they join the
- // same channel successfully using the same app id.
- // 2. If app certificate is turned on at dashboard, token is needed
- // when joining channel. The channel name and uid used to calculate
- // the token has to match the ones used for channel join
- await _engine.joinChannel(config.token, config.channelId, null, 0, null);
- }
- _addListener() {
- _engine.setEventHandler(RtcEngineEventHandler(warning: (warningCode) {
- log('Warning ${warningCode}');
- }, error: (errorCode) {
- log('Warning ${errorCode}');
- }, joinChannelSuccess: (channel, uid, elapsed) {
- log('joinChannelSuccess ${channel} ${uid} ${elapsed}');
- ;
- setState(() {
- isJoined = true;
- });
- }, userJoined: (uid, elapsed) {
- log('userJoined $uid $elapsed');
- this.setState(() {
- remoteUid = uid;
- });
- }, userOffline: (uid, reason) {
- log('userOffline $uid $reason');
- this.setState(() {
- remoteUid = null;
- });
- }, channelMediaRelayStateChanged:
- (ChannelMediaRelayState state, ChannelMediaRelayError code) {
- switch (state) {
- case ChannelMediaRelayState.Idle:
- log('ChannelMediaRelayState.Idle $code');
- this.setState(() {
- isRelaying = false;
- });
- break;
- case ChannelMediaRelayState.Connecting:
- log('ChannelMediaRelayState.Connecting $code)');
- break;
- case ChannelMediaRelayState.Running:
- log('ChannelMediaRelayState.Running $code)');
- this.setState(() {
- isRelaying = true;
- });
- break;
- case ChannelMediaRelayState.Failure:
- log('ChannelMediaRelayState.Failure $code)');
- this.setState(() {
- isRelaying = false;
- });
- break;
- default:
- log('default $code)');
- break;
- }
- }));
- }
- _onPressRelayOrStop() async {
- if (isRelaying) {
- await _engine.stopChannelMediaRelay();
- return;
- }
- if (_controller.text.length == 0) {
- return;
- }
- await _engine.startChannelMediaRelay(ChannelMediaRelayConfiguration(
- ChannelMediaInfo(config.channelId, 0, token: config.token),
- [ChannelMediaInfo('', 0, token: '')]));
- _controller.clear();
- }
- final TextEditingController _controller = TextEditingController();
- @override
- Widget build(BuildContext context) {
- return Stack(
- children: [
- Column(
- children: [
- !isJoined
- ? Row(
- children: [
- Expanded(
- flex: 1,
- child: ElevatedButton(
- onPressed: _initEngine,
- child: Text('Join channel'),
- ),
- )
- ],
- )
- : _renderVideo(),
- if (isJoined)
- Row(
- mainAxisSize: MainAxisSize.max,
- children: [
- Expanded(
- child: TextField(
- controller: _controller,
- decoration: InputDecoration(
- hintText: 'Enter target relay channel name',
- ))),
- ElevatedButton(
- onPressed: _onPressRelayOrStop,
- child: Text(!isRelaying ? 'Relay' : 'Stop'),
- ),
- ],
- )
- ],
- ),
- ],
- );
- }
- _renderVideo() {
- return Row(children: [
- Expanded(
- child: AspectRatio(
- aspectRatio: 1,
- child: RtcLocalView.SurfaceView(),
- )),
- Expanded(
- child: AspectRatio(
- aspectRatio: 1,
- child: remoteUid != null
- ? RtcRemoteView.SurfaceView(
- uid: remoteUid!,
- )
- : Container(
- color: Colors.grey[200],
- ),
- ),
- )
- ]);
- }
- }
|