Flutter亚马逊Chime会议集成插件eggnstone_amazon_chime的使用
Flutter亚马逊Chime会议集成插件eggnstone_amazon_chime的使用
简介
eggnstone_amazon_chime
是一个用于 Amazon Chime SDK 的封装,允许通过音频和视频加入 Chime 会议。
Android 注意事项
- Chime 不支持 Android 模拟器!
- 确保你的设备运行在 ARM 支持的设备(真实设备)或模拟器上。目前不支持 x86 模拟器。
- 设置应用的最低 SDK 版本为 23 或更高(因为 Chime 需要 API 级别 21,但平台视图无法在低于 API 级别 23 的版本上显示)。
- 使用的版本:v0.17.1。
iOS 注意事项
- 版本 2 及以上不支持 iOS。
- 需要维护者来支持 iOS 版本。
- 版本 1 支持 iOS,但由于文件大小问题,版本 2 及以上目前不支持 iOS。
- Chime 不支持 iOS 模拟器!
示例代码
以下是一个完整的示例 main.dart
文件,展示如何使用 eggnstone_amazon_chime
插件:
import 'dart:convert';
import 'dart:io';
import 'package:chime_example/MeetingSessionCreator.dart';
import 'package:chime_example/data/Attendee.dart';
import 'package:chime_example/data/Attendees.dart';
import 'package:device_info/device_info.dart';
import 'package:eggnstone_amazon_chime/eggnstone_amazon_chime.dart';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:permission_handler/permission_handler.dart';
void main() {
runApp(App());
}
class App extends StatefulWidget {
@override
_AppState createState() => _AppState();
}
class _AppState extends State<App> {
String _version = 'Unknown';
String _createMeetingSessionResult = 'CreateMeetingSession: Unknown';
String _audioVideoStartResult = 'AudioVideo: Unknown';
String _audioVideoStartLocalVideoResult = 'AudioVideoLocalVideo: Unknown';
String _audioVideoStartRemoteVideoResult = 'AudioVideoRemoteVideo: Unknown';
Attendees _attendees = Attendees();
bool _isAndroidEmulator = false;
bool _isIosSimulator = false;
@override
void initState() {
super.initState();
_startChime(); // 初始化 Chime
}
@override
Widget build(BuildContext context) {
var chimeViewChildren = List<Widget>.empty(growable: true);
if (_attendees.length == 0)
chimeViewChildren.add(Expanded(child: Center(child: Text('No attendees yet.'))));
else
for (int attendeeIndex = 0; attendeeIndex < _attendees.length; attendeeIndex++) {
Attendee attendee = _attendees[attendeeIndex];
if (attendee.videoView != null)
chimeViewChildren.add(
Expanded(
child: Center(
child: AspectRatio(
aspectRatio: attendee.aspectRatio,
child: attendee.videoView
)
)
)
);
}
var chimeViewColumn = Column(children: chimeViewChildren);
Widget content;
if (_isAndroidEmulator || _isIosSimulator)
content = Padding(
padding: const EdgeInsets.all(16),
child: Center(
child: Text('Chime does not support Android/iOS emulators/simulators.\n\nIf you see the SDK version above then the connection to the SDK works though.')
)
);
else
content = Column(
children: [
Text(_createMeetingSessionResult),
SizedBox(height: 8),
Row(
mainAxisAlignment: MainAxisAlignment.spaceAround,
children: [
Text('Audio/Video:'),
ElevatedButton(
child: Text('Start'),
onPressed: () => _audioVideoStart()
),
ElevatedButton(
child: Text('Stop'),
onPressed: () => _audioVideoStop()
)
]
),
Text(_audioVideoStartResult),
SizedBox(height: 8),
Row(
mainAxisAlignment: MainAxisAlignment.spaceAround,
children: [
Text('Local Video:'),
ElevatedButton(
child: Text('Start'),
onPressed: () => _audioVideoStartLocalVideo()
),
ElevatedButton(
child: Text('Stop'),
onPressed: () => _audioVideoStopLocalVideo()
)
]
),
Text(_audioVideoStartLocalVideoResult),
SizedBox(height: 8),
Row(
mainAxisAlignment: MainAxisAlignment.spaceAround,
children: [
Text('Remote Video:'),
ElevatedButton(
child: Text('Start'),
onPressed: () => _audioVideoStartRemoteVideo()
),
ElevatedButton(
child: Text('Stop'),
onPressed: () => _audioVideoStopRemoteVideo()
)
]
),
Text(_audioVideoStartRemoteVideoResult),
SizedBox(height: 8),
Expanded(child: chimeViewColumn)
]
);
return MaterialApp(
home: Scaffold(
appBar: AppBar(title: Text('ChimePlugin')),
body: Column(
children: [
SizedBox(height: 8),
Text(_version),
SizedBox(height: 8),
Expanded(child: content)
]
)
)
);
}
void _startChime() async {
await _getVersion();
if (Platform.isAndroid) {
DeviceInfoPlugin deviceInfo = DeviceInfoPlugin();
AndroidDeviceInfo androidInfo = await deviceInfo.androidInfo;
if (androidInfo.isPhysicalDevice) {
_addListener();
await _createMeetingSession();
} else {
setState(() {
_isAndroidEmulator = true;
});
}
} else if (Platform.isIOS) {
DeviceInfoPlugin deviceInfo = DeviceInfoPlugin();
IosDeviceInfo iosInfo = await deviceInfo.iosInfo;
if (iosInfo.isPhysicalDevice) {
_addListener();
await _createMeetingSession();
} else {
setState(() {
_isIosSimulator = true;
});
}
} else {
_addListener();
await _createMeetingSession();
}
}
Future<void> _getVersion() async {
String version;
try {
version = await Chime.version ?? '?';
} on PlatformException {
version = 'Failed to get version.';
}
if (mounted)
setState(() {
_version = version;
});
}
void _addListener() {
Chime.eventChannel.receiveBroadcastStream().listen(
(data) async {
dynamic event = JsonDecoder().convert(data);
String eventName = event['Name'];
dynamic eventArguments = event['Arguments'];
switch (eventName) {
case 'OnVideoTileAdded':
_handleOnVideoTileAdded(eventArguments);
break;
case 'OnVideoTileRemoved':
_handleOnVideoTileRemoved(eventArguments);
break;
default:
print('Warning: Unhandled event: $eventName');
print('Data: $data');
break;
}
},
onDone: () {
print('Chime.eventChannel.receiveBroadcastStream().listen()/onDone()');
},
onError: (e) {
print('Chime.eventChannel.receiveBroadcastStream().listen()/onError()');
}
);
}
Future<void> _createMeetingSession() async {
if (await Permission.microphone.request().isGranted == false) {
_createMeetingSessionResult = 'Need microphone permission.';
return;
}
if (await Permission.camera.request().isGranted == false) {
_createMeetingSessionResult = 'Need camera permission.';
return;
}
String meetingSessionState;
try {
// 需要提供自己的 AWS 账户和 Chime 配置数据
meetingSessionState = await MeetingSessionCreator().create() ?? 'OK';
} on PlatformException catch (e) {
meetingSessionState = 'Failed to create MeetingSession. PlatformException: $e';
} catch (e) {
meetingSessionState = 'Failed to create MeetingSession. Error: $e';
}
if (mounted)
setState(() {
_createMeetingSessionResult = meetingSessionState;
});
}
Future<void> _audioVideoStart() async {
String result;
try {
result = await Chime.audioVideoStart() ?? 'OK';
} on PlatformException catch (e) {
result = 'AudioVideoStart failed: PlatformException: $e';
} catch (e) {
result = 'AudioVideoStart failed: Error: $e';
}
if (mounted)
setState(() {
_audioVideoStartResult = result;
});
}
Future<void> _audioVideoStop() async {
String result;
try {
result = await Chime.audioVideoStop() ?? 'OK';
} on PlatformException catch (e) {
result = 'AudioVideoStop failed: PlatformException: $e';
} catch (e) {
result = 'AudioVideoStop failed: Error: $e';
}
if (mounted)
setState(() {
_audioVideoStartResult = result;
});
}
Future<void> _audioVideoStartLocalVideo() async {
String result;
try {
result = await Chime.audioVideoStartLocalVideo() ?? 'OK';
} on PlatformException catch (e) {
result = 'AudioVideoStartLocalVideo failed: PlatformException: $e';
} catch (e) {
result = 'AudioVideoStartLocalVideo failed: Error: $e';
}
if (mounted)
setState(() {
_audioVideoStartLocalVideoResult = result;
});
}
Future<void> _audioVideoStopLocalVideo() async {
String result;
try {
result = await Chime.audioVideoStopLocalVideo() ?? 'OK';
} on PlatformException catch (e) {
result = 'AudioVideoStopLocalVideo failed: PlatformException: $e';
} catch (e) {
result = 'AudioVideoStopLocalVideo failed: Error: $e';
}
if (mounted)
setState(() {
_audioVideoStartLocalVideoResult = result;
});
}
Future<void> _audioVideoStartRemoteVideo() async {
String result;
try {
result = await Chime.audioVideoStartRemoteVideo() ?? 'OK';
} on PlatformException catch (e) {
result = 'AudioVideoStartRemoteVideo failed: PlatformException: $e';
} catch (e) {
result = 'AudioVideoStartRemoteVideo failed: Error: $e';
}
if (mounted)
setState(() {
_audioVideoStartRemoteVideoResult = result;
});
}
Future<void> _audioVideoStopRemoteVideo() async {
String result;
try {
result = await Chime.audioVideoStopRemoteVideo() ?? 'OK';
} on PlatformException catch (e) {
result = 'AudioVideoStopRemoteVideo failed: PlatformException: $e';
} catch (e) {
result = 'AudioVideoStopRemoteVideo failed: Error: $e';
}
if (mounted)
setState(() {
_audioVideoStartRemoteVideoResult = result;
});
}
void _handleOnVideoTileAdded(dynamic arguments) async {
bool isLocalTile = arguments['IsLocalTile'];
int tileId = arguments['TileId'];
int videoStreamContentHeight = arguments['VideoStreamContentHeight'];
int videoStreamContentWidth = arguments['VideoStreamContentWidth'];
Attendee? attendee = _attendees.getByTileId(tileId);
if (attendee != null) {
print('_handleOnVideoTileAdded called but already mapped.');
return;
}
print('_handleOnVideoTileAdded: New attendee: TileId=$tileId => creating ChimeDefaultVideoRenderView');
attendee = Attendee(tileId, isLocalTile);
attendee.height = videoStreamContentHeight;
attendee.width = videoStreamContentWidth;
_attendees.add(attendee);
Attendee nonNullAttendee = attendee;
setState(() {
nonNullAttendee.setVideoView(
ChimeDefaultVideoRenderView(
onPlatformViewCreated: (int viewId) async {
nonNullAttendee.setViewId(viewId);
print('ChimeDefaultVideoRenderView created. Binding...');
await Chime.bindVideoView(nonNullAttendee.viewId!, nonNullAttendee.tileId);
print('ChimeDefaultVideoRenderView created. Bound.');
}
)
);
});
}
void _handleOnVideoTileRemoved(dynamic arguments) async {
int tileId = arguments['TileId'];
Attendee? attendee = _attendees.getByTileId(tileId);
if (attendee == null) {
print('Error: Could not find attendee for TileId=$tileId');
return;
}
print('_handleOnVideoTileRemoved: Found attendee. Unbinding...');
_attendees.remove(attendee);
await Chime.unbindVideoView(tileId);
print('_handleOnVideoTileRemoved: Found attendee. Unbound.');
setState(() {
// refresh
});
}
}
更多关于Flutter亚马逊Chime会议集成插件eggnstone_amazon_chime的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html
更多关于Flutter亚马逊Chime会议集成插件eggnstone_amazon_chime的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html
当然,以下是一个关于如何在Flutter项目中集成并使用eggnstone_amazon_chime
插件来加入Amazon Chime会议的示例代码。请注意,为了成功运行此代码,你需要确保已经安装了Flutter和Dart环境,并且在你的项目中正确添加了eggnstone_amazon_chime
插件。
首先,你需要在pubspec.yaml
文件中添加eggnstone_amazon_chime
依赖:
dependencies:
flutter:
sdk: flutter
eggnstone_amazon_chime: ^最新版本号 # 请替换为实际发布的最新版本号
然后运行flutter pub get
来安装依赖。
接下来,是一个基本的Flutter应用示例,展示了如何使用eggnstone_amazon_chime
插件加入Amazon Chime会议:
import 'package:flutter/material.dart';
import 'package:eggnstone_amazon_chime/eggnstone_amazon_chime.dart';
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Amazon Chime Example',
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: MyHomePage(),
);
}
}
class MyHomePage extends StatefulWidget {
@override
_MyHomePageState createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
AmazonChimeClient? chimeClient;
@override
void initState() {
super.initState();
// 初始化Amazon Chime客户端
initializeChimeClient();
}
void initializeChimeClient() async {
// 配置你的Amazon Chime凭证和其他必要信息
final credentials = AmazonChimeCredentials(
accessKeyId: '你的AccessKeyID',
secretAccessKey: '你的SecretAccessKey',
sessionToken: '你的SessionToken', // 如果使用临时凭证,需要提供
region: '你的Region', // 例如 'us-west-2'
);
// 创建Amazon Chime客户端实例
chimeClient = AmazonChimeClient(credentials: credentials);
// 你可以在这里添加更多初始化代码,比如创建会议、获取会议详情等
// ...
}
void joinMeeting() async {
if (chimeClient == null) {
print('Chime client is not initialized.');
return;
}
// 配置会议信息
final meetingInfo = MeetingInfo(
meetingId: '你的MeetingID',
externalMeetingId: '你的ExternalMeetingID', // 如果需要
attendeeId: '你的AttendeeID',
joinToken: '你的JoinToken',
);
try {
// 加入会议
await chimeClient!.startMeeting(meetingInfo: meetingInfo);
print('Joined the meeting successfully.');
} catch (e) {
print('Failed to join the meeting: $e');
}
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('Flutter Amazon Chime Example'),
),
body: Center(
child: ElevatedButton(
onPressed: joinMeeting,
child: Text('Join Meeting'),
),
),
);
}
}
在这个示例中,我们定义了一个简单的Flutter应用,其中包含一个按钮用于加入Amazon Chime会议。在initializeChimeClient
方法中,我们初始化了Amazon Chime客户端,并配置了必要的凭证信息。在joinMeeting
方法中,我们配置了会议信息并尝试加入会议。
请注意,为了运行这个示例,你需要提供有效的Amazon Chime凭证(accessKeyId
, secretAccessKey
, sessionToken
)和会议信息(meetingId
, externalMeetingId
, attendeeId
, joinToken
)。这些信息通常是从你的Amazon Chime后端服务获取的。
此外,由于Amazon Chime SDK for Flutter可能包含一些额外的配置步骤和依赖项,建议查阅eggnstone_amazon_chime的官方文档(如果可用)以获取更详细的信息和最新的使用指南。