- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我正在使用 Agora在 Flutter 中进行一对一视频聊天.User1有一个应用要上线,user2有另一个应用要上线。两人上网后,就可以进行视频聊天了。 这两个应用的代码库几乎相似。
我有一个屏幕或 Activity (例如屏幕 1),其中在点击按钮(例如按钮 1)时会显示一个警告对话框。点击警告对话框中的 Continue
按钮,对话框消失,用户被带到进行视频聊天的屏幕(比如屏幕 2)。但是在成功进入视频聊天屏幕后,如果用户点击移动设备上的后退按钮,那么她/他将被带到屏幕 1,并且在点击按钮 1 之后,如果用户点击 Continue
弹出警报对话框中的按钮,用户再次被带到屏幕 2,但这次本地视频(即用户使用该应用程序的视频)一直在加载。显然,我希望本地视频像第一次那样加载。
我会以您可以轻松运行的方式将我的代码放在这里。
以下代码适用于 user1。对于 user2,应用程序中没有警告框。来自 user1 的相同代码用于 user2 应用程序,除了 remoteUid
的值对于 user2 设置为 2 而该值对于 user1 设置为 1。这些只是标识 2 个用户的两个值。
对于用户 1:
main.dart:
import 'dart:async';
import 'dart:convert';
import 'package:flutter/material.dart';
import 'livesession1to1.dart';
void main() {
runApp(MessagingExampleApp());
}
class NavigationService {
static GlobalKey<NavigatorState> navigatorKey =
GlobalKey<NavigatorState>();
}
/// Entry point for the example application.
class MessagingExampleApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Messaging Example App',
navigatorKey: NavigationService.navigatorKey, // set property
theme: ThemeData.dark(),
routes: {
'/': (context) => Application(),
'/liveSession1to1': (context) =>LiveSession1to1(),
},
);
}
}
int _messageCount = 0;
/// The API endpoint here accepts a raw FCM payload for demonstration purposes.
String constructFCMPayload(String? token, String server_key) {
_messageCount++;
return jsonEncode({
'token': token,
'to':token,
'data': {
'via': 'FlutterFire Cloud Messaging!!!',
'count': _messageCount.toString(),
},
'notification': {
'title': 'Hello FlutterFire!',
'body': 'This notification (#$_messageCount) was created via FCM! =============',
},
"delay_while_idle" : false,
"priority" : "high",
"content_available" : true
});
}
/// Renders the example application.
class Application extends StatefulWidget {
@override
State<StatefulWidget> createState() => _Application();
}
class _Application extends State<Application> {
String? _token;
@override
void initState() {
super.initState();
}
showAlertDialog() {
BuildContext context=NavigationService.navigatorKey.currentContext!;
// set up the buttons
Widget cancelButton = TextButton(
child: Text("Cancel"),
onPressed: () {},
);
Widget continueButton = TextButton(
child: Text("Continue"),
onPressed: () {
Navigator.of(context, rootNavigator: true).pop();
Navigator.of(context).pushNamed('/liveSession1to1');
},
);
Timer? timer = Timer(Duration(milliseconds: 5000), (){
Navigator.of(context, rootNavigator: true).pop();
});
showDialog(
context: context,
builder: (BuildContext builderContext) {
return AlertDialog(
backgroundColor: Colors.black26,
title: Text('One to one live session'),
content: SingleChildScrollView(
child: Text('Do you want to connect for a live session ?'),
),
actions: [
cancelButton,
continueButton,
],
);
}
).then((value){
// dispose the timer in case something else has triggered the dismiss.
timer?.cancel();
timer = null;
});
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text('My App'),
),
floatingActionButton: Builder(
builder: (context) => FloatingActionButton(
onPressed: showAlertDialog,
backgroundColor: Colors.white,
child: const Icon(Icons.send),
),
),
body: SingleChildScrollView(
child: Text(
'Trigger Alert'
),
),
);
}
}
livesession1to1.dart:
import 'dart:async';
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:flutter/material.dart';
import 'package:permission_handler/permission_handler.dart';
// const appId = "<-- Insert App Id -->";
// const token = "<-- Insert Token -->";
const appId = "......";// Put Agora App ID from Agora site here
const token = "....";// Put token ( temporary token avilable from Agora site)
void main() => runApp(MaterialApp(home: LiveSession1to1()));
class LiveSession1to1 extends StatefulWidget {
@override
_LiveSession1to1State createState() => _LiveSession1to1State();
}
class _LiveSession1to1State extends State<LiveSession1to1> {
int _remoteUid=1;
bool _localUserJoined = false;
late RtcEngine _engine;
@override
void initState() {
super.initState();
setState(() {});
initAgora();
}
Future<void> initAgora() async {
// retrieve permissions
await [Permission.microphone, Permission.camera].request();
// Create RTC client instance
RtcEngineContext context = RtcEngineContext(appId);
_engine = await RtcEngine.createWithContext(context);
await _engine.enableVideo();
_engine.setEventHandler(
RtcEngineEventHandler(
joinChannelSuccess: (String channel, int uid, int elapsed) {
print("local user $uid joined");
setState(() {
_localUserJoined = true;
});
},
userJoined: (int uid, int elapsed) {
print("remote user $uid joined");
setState(() {
_remoteUid = uid;
});
},
userOffline: (int uid, UserOfflineReason reason) {
print("remote user $uid left channel");
setState(() {
// _remoteUid = null;
_remoteUid = 0;
});
},
),
);
try {
await _engine.joinChannel(token, "InstaClass", null, 0);
} catch (e) {
print("error with agora = ");
print("$e");
print("error printeddddd");
}
}
// Create UI with local view and remote view
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text('Agora Video Call'),
),
body: Stack(
children: [
Center(
child: _remoteVideo(),
),
Align(
alignment: Alignment.topLeft,
child: Container(
width: 100,
height: 150,
child: Center(
child: _localUserJoined
? RtcLocalView.SurfaceView()
: CircularProgressIndicator(),
),
),
),
],
),
);
}
// Display remote user's video
Widget _remoteVideo() {
if (_remoteUid != 0) {
return RtcRemoteView.SurfaceView(
uid: _remoteUid,
channelId: "InstaClass",
);
}else {
print("'Please wait for remote user to join',");
return Text(
'Please wait for remote user to join',
textAlign: TextAlign.center,
);
}
}
}
对于用户 2:
main.dart:
import 'dart:async';
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:flutter/material.dart';
import 'package:permission_handler/permission_handler.dart';
const appId = "....."; // Same as user1 app
const token = "....."; // same as user1 app
void main() => runApp(MaterialApp(home: MyApp()));
class MyApp extends StatefulWidget {
@override
_MyAppState createState() => _MyAppState();
}
class _MyAppState extends State<MyApp> {
// int? _remoteUid=1;
int _remoteUid=2;
bool _localUserJoined = false;
late RtcEngine _engine;
@override
void initState() {
super.initState();
initAgora();
}
Future<void> initAgora() async {
// retrieve permissions
await [Permission.microphone, Permission.camera].request();
//create the engine
_engine = await RtcEngine.create(appId);
await _engine.enableVideo();
_engine.setEventHandler(
RtcEngineEventHandler(
joinChannelSuccess: (String channel, int uid, int elapsed) {
print("local user $uid joined");
setState(() {
_localUserJoined = true;
});
},
userJoined: (int uid, int elapsed) {
print("remote user $uid joined");
setState(() {
_remoteUid = uid;
});
},
userOffline: (int uid, UserOfflineReason reason) {
print("remote user $uid left channel");
setState(() {
// _remoteUid = null;
_remoteUid = 0;
});
},
),
);
// await _engine.joinChannel(token, "test", null, 0);
await _engine.joinChannel(token, "InstaClass", null, 0);
}
// Create UI with local view and remote view
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text('Agora Video Call'),
),
body: Stack(
children: [
Center(
child: _remoteVideo(),
),
Align(
alignment: Alignment.topLeft,
child: Container(
width: 100,
height: 150,
child: Center(
child: _localUserJoined
? RtcLocalView.SurfaceView()
: CircularProgressIndicator(),
),
),
),
],
),
);
}
// Display remote user's video
Widget _remoteVideo() {
/*if (_remoteUid != null) {
return RtcRemoteView.SurfaceView(uid: _remoteUid!);
}*/
if (_remoteUid != 0) {
return RtcRemoteView.SurfaceView(
uid: _remoteUid,
channelId: "InstaClass",
);
}else {
return Text(
'Please wait for remote user to join',
textAlign: TextAlign.center,
);
}
}
}
为了获取应用程序 ID 和 token ,请登录 Agora 站点。登录后,转到“项目管理”部分以查看已在此处创建的项目。在 Functions
列下,单击 key 符号,您将被带到一个页面,您可以在其中生成临时 token 。在该页面上,为 channel 名称输入值“InstaClass”,因为我在我的代码中使用了这个名称。
如何让视频聊天一次顺畅之后顺畅顺畅?
最佳答案
我认为问题在于当按下 back
按钮时,您只是被带到上一个屏幕并且调用 session
没有结束。您可以尝试在按返回按钮时离开
channel ,例如:
_engine.leaveChannel();
结束通话
按钮示例
ElevatedButton(
onPressed: () {
_rtcEngine.leaveChannel();
Navigator.pop(context);
},
style: ButtonStyle(
shape: MaterialStateProperty.all(CircleBorder()),
backgroundColor: MaterialStateProperty.all(Colors.red),
padding: MaterialStateProperty.all(
EdgeInsets.fromLTRB(15, 15, 15, 12)),
),
child: Icon(
Icons.phone,
size: 30,
),
)
后退按钮
使用 WillPopScope 覆盖
return WillPopScope(
onWillPop: () async {
_rtcEngine.leaveChannel();
return true;
},
child: Scaffold(
body: Container(),
),
);
关于android - Flutter 中的 Agora - 多次导航到视频聊天屏幕使本地视频永远加载,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/70536664/
在 Agora FAQ 中我看到一个 channel 支持 17 个流并发。这是在 channel 中只有音频或低质量视频流的情况下的限制吗? 正如我在 Agora sdk 4.x 中看到的,流被轨道
我正在尝试使用 Agora Rtc WEB api 进行语音/视频聊天。 这只是一对一的通话,我希望一方可以调用通知/向另一方发送消息(例如,在 Skype 中发送表情符号“调用 react ”之类的
我正在使用 Agora.io 构建网络应用程序。我希望能够在客户的智能手机上从前置摄像头切换到后置摄像头。我看过 switchCamera 的 agora 文档。我尝试了以下方法: switchCam
我正在我的应用程序中使用 token 设置身份验证,但遇到了 DYNAMIC_KEY_EXPIRED 问题,该问题将我锁定在所有 Agora 服务之外。 我通过文档中提供的 RtcTokenBuild
我们使用来自https://github.com/AgoraIO-Community/Angular-Agora-RTC的样本 channel 名称硬编码在示例中。当 2 个用户需要连接通话时。理想情
我正在使用 Agora 的 Web SDK 进行群组音频通话。我正在尝试实现一个简单的静音按钮,用户在通话后可以单击该按钮以将其音频静音。 当本地用户将他们的麦克风静音时,远程用户应该会看到该用户的麦
我正在使用 Agora 的 Web SDK 进行群组音频通话。我正在尝试实现一个简单的静音按钮,用户在通话后可以单击该按钮以将其音频静音。 当本地用户将他们的麦克风静音时,远程用户应该会看到该用户的麦
我正在使用 Unreal Engine4 制作一个 Android 应用程序。 我想将 Agora 应用到 Android 应用程序中。 https://docs.agora.io/en/Intera
我正在使用 3d 麦克风,它使用 1/8 插孔插入适配器,在 iPhone 上就像一个魅力。它适用于相机应用程序,所以我知道硬件能够接收立体声。 但是在我的 agora.io iPhone 应用程序中
SDK:声网视频通话 平台:电视 操作系统:安卓 问题:我最近将 Agora 的视频通话服务集成到我们的应用程序中,每当我发起视频通话时,布局似乎杂乱无章,新条目垂直添加。有人可以帮我弄这个吗?谢谢你
因为我们已经下载了实时消息传递(测试版),然后我们运行了演示,但是在 apk 运行时它要求我们提供一个 UserId(帐户),所以我对此感到困惑所以你能给我建议吗实时消息传递的用户 ID(帐户)是什么
使用给定的代码示例,我们尝试进行文本聊天并且它正在工作。我们想在同一个聊天窗口中使用文档共享,但我没有看到任何相同的代码示例。不确定 Agora.io 是否提供此功能。有没有人尝试使用 Agora.i
我想像 Messenger (Facebook) 那样添加应用内(视频)调用。当一方创建 channel 而另一方加入时,它起作用。 但是有没有办法创建通话屏幕,让 B 方可以接听或拒绝来电?我正在查
我能够编译项目,但它一启动就崩溃了。我已在实体 Samsung Galaxy S8 和模拟 Pixel 3 上对此进行了测试。两者都产生相同的结果。 AGApplication.java 中的第 15
我目前正在开发 Agora.io 服务,这些服务为我们提供了 audio,video,one-to-one and broadcast communication 我已经在给定示例的帮助下成功实现了这
我第一次尝试制作视频通话应用。我在 android studio 中使用 Agora.io 进行视频通话。我面临的问题是我看不到我打电话的人的视频。我完美地从前置摄像头获得了我自己的。 我被这个问题困
我一直在开发一个应用程序,我需要在我的应用程序中实现音频和视频通话,这是我使用 Agora.io 完成的,但问题是我必须显示来电通知,如果应用程序在前景或背景。我已经尝试了很多东西,但我仍然无法配置它
我已经在我的应用程序中实现了agora语音通话。它在旧设备和选项卡上工作正常,但在新设备上锁定屏幕 1 分钟后,接收器无法听到音频。我猜 Android 系统将应用程序置于 sleep 模式。 我尝试
我正在使用 Agora在 Flutter 中进行一对一视频聊天.User1有一个应用要上线,user2有另一个应用要上线。两人上网后,就可以进行视频聊天了。 这两个应用的代码库几乎相似。 我有一个屏幕
我正在使用 agora io 进行视频通话和屏幕共享。屏幕共享工作正常。但问题是当我取消屏幕共享时,流没有显示。但加入仍然有效。我需要捕捉屏幕共享的取消事件。我已经阅读了文档,但没有关于取消事件的线索
我是一名优秀的程序员,十分优秀!