我已经在我的flutter应用程序中实现了agora sdk,但是当我点击endCall按钮时,如果点击的人是呼叫者,他们都会结束通话,但是当我从接收器点击endCall时,视频屏幕不会消失离开,直到呼叫者也点击结束呼叫按钮。
当您开始通话时,用户会创建自己的 Agora RtcEngine 实例,当您使用它加入频道时,每个用户都需要单独从前端离开频道。但是,如果您希望主持人或某个人拥有这样的权限,以便当该用户离开时,频道中所有其他用户的通话都会结束,那么您需要设置踢出规则。这可以通过 Agora 提供的 RESTful API 来完成。您可以在这里查看:https://docs.agora.io/en/rtc/restfulapi/#/Banning%20user%20privileges/createKickingRule
full code for agora flutter :
import 'dart:math';
import 'package:agora_rtc_engine/agora_rtc_engine.dart';
import 'package:flutter/material.dart';
import 'package:flutter/scheduler.dart';
import 'package:get/get.dart';
import 'package:medical_app/view_model/Home/home_screen.dart';
// import 'package:agora_rtc_engine/rtc_engine.dart';
import 'package:permission_handler/permission_handler.dart';
import '../../main.dart';
import '../../utils/appID.dart';
import '../Profile/oppointment.dart';
class CallPage extends StatefulWidget {
final String token;
const CallPage({ required this.token}) : super();
@override
_CallPageState createState() => _CallPageState();
}
class _CallPageState extends State<CallPage> {
int? _remoteUid; // uid of the remote user
bool _isJoined = false; // Indicates if the local user has joined the channel
RtcEngine? agoraEngine;
// Agora engine instance
int uid = 0;
final GlobalKey<ScaffoldMessengerState> scaffoldMessengerKey =
GlobalKey<ScaffoldMessengerState>(); // Global key to access the scaffold
showMessage(String message) {
scaffoldMessengerKey.currentState?.showSnackBar(SnackBar(
content: Text(message),
));
}
Future<void> _handleCameraAndMic(Permission permission) async {
final status = await permission.request();
print(status);
}
bool engineload = true;
@override
void initState() {
setupVideoSDKEngine();
super.initState();
}
@override
void didChangeDependencies() async {
_handleCameraAndMic(Permission.camera);
_handleCameraAndMic(Permission.microphone);
await setupVideoSDKEngine();
super.didChangeDependencies();
}
// Build UI
@override
Widget build(BuildContext context) {
debugPrint("The Agora Token is ......******************* ${widget.token}");
return Scaffold(
key:scaffoldMessengerKey,
appBar: AppBar(
title: const Text('Get started with Video Calling'),
leading: IconButton(onPressed: () async {
leave();
await agoraEngine!.leaveChannel();
await agoraEngine!.release();
Navigator.pushAndRemoveUntil(context, MaterialPageRoute(builder: (BuildContext context) {
return const HomeScreen();
}), (route) => false);
}, icon: const Icon(Icons.arrow_back),),
),
body: engineload ? const Center(child: CircularProgressIndicator.adaptive(),): ListView(
padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 4),
children: [
// Container for the local video
Container(
height: 240,
decoration: BoxDecoration(border: Border.all()),
child: Center(child: _localPreview()),
),
const SizedBox(height: 10),
//Container for the Remote video
Container(
height: 240,
decoration: BoxDecoration(border: Border.all()),
child: Center(child: _remoteVideo()),
),
// Button Row
Row(
children: <Widget>[
Expanded(
child: ElevatedButton(
onPressed: _isJoined ? null : () => {join()},
child: const Text("Join"),
),
),
const SizedBox(width: 10),
Expanded(
child: ElevatedButton(
onPressed: _isJoined ? () => {leave()} : null,
child: const Text("Leave"),
),
),
],
),
// Button Row ends
],
));
}
// Display local video preview
Widget _localPreview() {
if (_isJoined) {
return AgoraVideoView(
controller: VideoViewController(
rtcEngine: agoraEngine!,
canvas: VideoCanvas(uid: uid),
),
);
} else {
return const Text(
'Join a channel',
textAlign: TextAlign.center,
);
}
}
// Display remote user's video
Widget _remoteVideo() {
if (_remoteUid != null) {
return AgoraVideoView(
controller: VideoViewController.remote(
rtcEngine: agoraEngine!,
canvas: VideoCanvas(uid: _remoteUid),
connection: const RtcConnection(channelId:"Input Channel Here"),
),
);
} else {
String msg = '';
if (_isJoined) msg = 'Waiting for a remote user to join';
return Text(
msg,
textAlign: TextAlign.center,
);
}
}
Future<void> setupVideoSDKEngine() async {
// retrieve or request camera and microphone permissions
await [Permission.microphone, Permission.camera].request();
//create an instance of the Agora engine
agoraEngine = createAgoraRtcEngine();
await agoraEngine!.initialize(RtcEngineContext(appId: appID)).then((value) {
setState(() {
engineload = false;
});
debugPrint("Engine connected");
});
await agoraEngine!.enableVideo();
// Register the event handler
agoraEngine!.registerEventHandler(
RtcEngineEventHandler(
onJoinChannelSuccess: (RtcConnection connection, int elapsed) {
showMessage(
"Local user uid:${connection.localUid} joined the channel");
setState(() {
_isJoined = true;
});
},
onUserJoined: (RtcConnection connection, int remoteUid, int elapsed) {
showMessage("Remote user uid:$remoteUid joined the channel");
setState(() {
_remoteUid = remoteUid;
});
},
onUserOffline: (RtcConnection connection, int remoteUid,
UserOfflineReasonType reason) {
showMessage("Remote user uid:$remoteUid left the channel");
setState(() {
_remoteUid = 1;
});
},
),
);
}
void join() async {
await agoraEngine!.startPreview();
debugPrint("Join is cliked");
// Set channel options including the client role and channel profile
ChannelMediaOptions options = const ChannelMediaOptions(
clientRoleType: ClientRoleType.clientRoleBroadcaster,
channelProfile: ChannelProfileType.channelProfileCommunication,
);
await agoraEngine!.joinChannel(
token: widget.token,
channelId: "Enter your Channel name here",
options: options,
uid:uid,
).then((value) {
debugPrint("Agora Connected");
}).onError((error, stackTrace) {
debugPrint("The Agora Error is ... $error");
}).then((value) {
debugPrint("The Call is joined");
}).onError((error, stackTrace) {
debugPrint("The Agora Join Error : $error");
});
}
void leave() async {
setState(() {
_isJoined = false;
_remoteUid = 1;
});
await agoraEngine!.leaveChannel();
await agoraEngine!.release();
Navigator.pushAndRemoveUntil(context, MaterialPageRoute(builder: (BuildContext context) {
return const HomeScreen();
}), (route) => false);
}
// Release the resources when you leave
@override
void dispose() async {
await agoraEngine!.leaveChannel();
await agoraEngine!.release();
super.dispose();
}
}