问题描述
我想在我的应用程序中进行视频电话会议,任何人都知道如何做到这一点,除了agora,因为我已经知道了,但它是付费的。那么还有其他解决方案吗?
还有一件事在颤振中支持缩放吗?
解决方法
是的,您可以为此使用 jitsi_meet
包:示例如下:
import 'dart:io';
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:jitsi_meet/feature_flag/feature_flag.dart';
import 'package:jitsi_meet/jitsi_meet.dart';
import 'package:jitsi_meet/jitsi_meeting_listener.dart';
import 'package:jitsi_meet/room_name_constraint.dart';
import 'package:jitsi_meet/room_name_constraint_type.dart';
void main() => runApp(MyApp());
class MyApp extends StatefulWidget {
@override
_MyAppState createState() => _MyAppState();
}
class _MyAppState extends State<MyApp> {
final serverText = TextEditingController();
final roomText = TextEditingController(text: "plugintestroom");
final subjectText = TextEditingController(text: "My Plugin Test Meeting");
final nameText = TextEditingController(text: "Plugin Test User");
final emailText = TextEditingController(text: "fake@email.com");
var isAudioOnly = true;
var isAudioMuted = true;
var isVideoMuted = true;
@override
void initState() {
super.initState();
JitsiMeet.addListener(JitsiMeetingListener(
onConferenceWillJoin: _onConferenceWillJoin,onConferenceJoined: _onConferenceJoined,onConferenceTerminated: _onConferenceTerminated,onPictureInPictureWillEnter: _onPictureInPictureWillEnter,onPictureInPictureTerminated: _onPictureInPictureTerminated,onError: _onError));
}
@override
void dispose() {
super.dispose();
JitsiMeet.removeAllListeners();
}
@override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
appBar: AppBar(
title: const Text('Plugin example app'),),body: Container(
padding: const EdgeInsets.symmetric(
horizontal: 16.0,child: SingleChildScrollView(
child: Column(
children: <Widget>[
SizedBox(
height: 24.0,TextField(
controller: serverText,decoration: InputDecoration(
border: OutlineInputBorder(),labelText: "Server URL",hintText: "Hint: Leave empty for meet.jitsi.si"),SizedBox(
height: 16.0,TextField(
controller: roomText,decoration: InputDecoration(
border: OutlineInputBorder(),labelText: "Room",TextField(
controller: subjectText,labelText: "Subject",TextField(
controller: nameText,labelText: "Display Name",TextField(
controller: emailText,labelText: "Email",CheckboxListTile(
title: Text("Audio Only"),value: isAudioOnly,onChanged: _onAudioOnlyChanged,CheckboxListTile(
title: Text("Audio Muted"),value: isAudioMuted,onChanged: _onAudioMutedChanged,CheckboxListTile(
title: Text("Video Muted"),value: isVideoMuted,onChanged: _onVideoMutedChanged,Divider(
height: 48.0,thickness: 2.0,SizedBox(
height: 64.0,width: double.maxFinite,child: RaisedButton(
onPressed: () {
_joinMeeting();
},child: Text(
"Join Meeting",style: TextStyle(color: Colors.white),color: Colors.blue,SizedBox(
height: 48.0,],);
}
_onAudioOnlyChanged(bool value) {
setState(() {
isAudioOnly = value;
});
}
_onAudioMutedChanged(bool value) {
setState(() {
isAudioMuted = value;
});
}
_onVideoMutedChanged(bool value) {
setState(() {
isVideoMuted = value;
});
}
_joinMeeting() async {
String serverUrl =
serverText.text?.trim()?.isEmpty ?? "" ? null : serverText.text;
try {
// Enable or disable any feature flag here
// If feature flag are not provided,default values will be used
// Full list of feature flags (and defaults) available in the README
FeatureFlag featureFlag = FeatureFlag();
featureFlag.welcomePageEnabled = false;
// Here is an example,disabling features for each platform
if (Platform.isAndroid) {
// Disable ConnectionService usage on Android to avoid issues (see README)
featureFlag.callIntegrationEnabled = false;
} else if (Platform.isIOS) {
// Disable PIP on iOS as it looks weird
featureFlag.pipEnabled = false;
}
//uncomment to modify video resolution
//featureFlag.resolution = FeatureFlagVideoResolution.MD_RESOLUTION;
// Define meetings options here
var options = JitsiMeetingOptions()
..room = roomText.text
..serverURL = serverUrl
..subject = subjectText.text
..userDisplayName = nameText.text
..userEmail = emailText.text
..audioOnly = isAudioOnly
..audioMuted = isAudioMuted
..videoMuted = isVideoMuted
..featureFlag = featureFlag;
debugPrint("JitsiMeetingOptions: $options");
await JitsiMeet.joinMeeting(
options,listener: JitsiMeetingListener(onConferenceWillJoin: ({message}) {
debugPrint("${options.room} will join with message: $message");
},onConferenceJoined: ({message}) {
debugPrint("${options.room} joined with message: $message");
},onConferenceTerminated: ({message}) {
debugPrint("${options.room} terminated with message: $message");
},onPictureInPictureWillEnter: ({message}) {
debugPrint("${options.room} entered PIP mode with message: $message");
},onPictureInPictureTerminated: ({message}) {
debugPrint("${options.room} exited PIP mode with message: $message");
}),// by default,plugin default constraints are used
//roomNameConstraints: new Map(),// to disable all constraints
//roomNameConstraints: customContraints,// to use your own constraint(s)
);
} catch (error) {
debugPrint("error: $error");
}
}
static final Map<RoomNameConstraintType,RoomNameConstraint>
customContraints = {
RoomNameConstraintType.MAX_LENGTH: new RoomNameConstraint((value) {
return value.trim().length <= 50;
},"Maximum room name length should be 30."),RoomNameConstraintType.FORBIDDEN_CHARS: new RoomNameConstraint((value) {
return RegExp(r"[$€£]+",caseSensitive: false,multiLine: false)
.hasMatch(value) ==
false;
},"Currencies characters aren't allowed in room names."),};
void _onConferenceWillJoin({message}) {
debugPrint("_onConferenceWillJoin broadcasted with message: $message");
}
void _onConferenceJoined({message}) {
debugPrint("_onConferenceJoined broadcasted with message: $message");
}
void _onConferenceTerminated({message}) {
debugPrint("_onConferenceTerminated broadcasted with message: $message");
}
void _onPictureInPictureWillEnter({message}) {
debugPrint("_onPictureInPictureWillEnter broadcasted with message: $message");
}
void _onPictureInPictureTerminated({message}) {
debugPrint("_onPictureInPictureTerminated broadcasted with message: $message");
}
_onError(error) {
debugPrint("_onError broadcasted: $error");
}
}