Flutter视频投射插件flutter_video_cast_v2的使用
Flutter视频投射插件flutter_video_cast_v2的使用
flutter_video_cast_v2
是一个用于在 Flutter 应用程序中连接到 Chromecast 和 Apple TV 等投射设备的插件。以下是如何在你的 Flutter 应用程序中使用这个插件的详细步骤。
安装
首先,在 pubspec.yaml
文件中添加 flutter_video_cast_v2
作为依赖项:
dependencies:
flutter_video_cast_v2: ^版本号
然后运行 flutter pub get
来获取新的依赖项。
iOS 配置
- 将项目的最低操作系统目标设置为 iOS 11.0。
- 在
ios/Runner/AppDelegate.m
中初始化 Cast 上下文:
import UIKit
import Flutter
import GoogleCast
@UIApplicationMain
@objc class AppDelegate: FlutterAppDelegate, GCKLoggerDelegate {
let kReceiverAppID = kGCKDefaultMediaReceiverApplicationID
let kDebugLoggingEnabled = true
override func application(
_ application: UIApplication,
didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?
) -> Bool {
GeneratedPluginRegistrant.register(with: self)
let criteria = GCKDiscoveryCriteria(applicationID: kReceiverAppID)
let options = GCKCastOptions(discoveryCriteria: criteria)
GCKCastContext.setSharedInstanceWith(options)
GCKCastContext.sharedInstance().useDefaultExpandedMediaControls = true
GCKLogger.sharedInstance().delegate = self
return super.application(application, didFinishLaunchingWithOptions: launchOptions)
}
}
- 为了允许嵌入视图预览,在应用的
Info.plist
文件中添加一个布尔属性,键为io.flutter.embedded_views_preview
,值为YES
。
Android 配置
- 在模块(应用级别)的 Gradle 文件(通常为
android/app/build.gradle
)中添加依赖项:
implementation 'com.google.android.gms:play-services-cast-framework:19.0.0'
implementation 'com.google.android.exoplayer:extension-cast:2.11.5'
- 在应用的
AndroidManifest.xml
文件中将MainActivity
的主题设置为@style/Theme.AppCompat.NoActionBar
:
<manifest ...>
<application ...
<meta-data android:name="com.google.android.gms.cast.framework.OPTIONS_PROVIDER_CLASS_NAME"
android:value="com.google.android.exoplayer2.ext.cast.DefaultCastOptionsProvider"/>
...
<activity android:theme="@style/Theme.AppCompat.NoActionBar" ...
- 让
MainActivity
继承FlutterFragmentActivity
并初始化 Cast 上下文:
CastContext.getSharedInstance(applicationContext)
通用配置
现在,你可以在你的小部件树中添加一个 ChromeCastButton
小部件。按钮可以通过 ChromeCastController
控制,该控制器通过 ChromeCastButton
的 onButtonCreated
回调传递。
以下是完整的示例代码:
import 'package:flutter/material.dart';
import 'package:flutter_video_cast/flutter_video_cast.dart';
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
[@override](/user/override)
Widget build(BuildContext context) {
return MaterialApp(
home: CastSample(),
);
}
}
class CastSample extends StatefulWidget {
[@override](/user/override)
_CastSampleState createState() => _CastSampleState();
}
class _CastSampleState extends State<CastSample> {
ChromeCastController? _controller;
[@override](/user/override)
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('Cast Sample'),
actions: [
ChromeCastButton(
onButtonCreated: (controller) {
setState(() => _controller = controller);
_controller?.addSessionListener();
},
onSessionStarted: () {
_controller?.loadMedia('https://commondatastorage.googleapis.com/gtv-videos-bucket/sample/BigBuckBunny.mp4');
},
),
],
),
);
}
}
完整示例代码
以下是完整的示例代码,展示了如何在 Flutter 应用程序中使用 flutter_video_cast_v2
插件:
import 'package:flutter/material.dart';
import 'package:flutter_video_cast/flutter_video_cast.dart';
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
[@override](/user/override)
Widget build(BuildContext context) {
return MaterialApp(home: CastSample());
}
}
class CastSample extends StatefulWidget {
static const _iconSize = 50.0;
[@override](/user/override)
_CastSampleState createState() => _CastSampleState();
}
class _CastSampleState extends State<CastSample> {
late ChromeCastController _controller;
AppState _state = AppState.idle;
bool? _playing = false;
[@override](/user/override)
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('Plugin example app'),
actions: [
AirPlayButton(
size: CastSample._iconSize,
color: Colors.white,
activeColor: Colors.amber,
onRoutesOpening: () => print('opening'),
onRoutesClosed: () => print('closed'),
),
ChromeCastButton(
size: CastSample._iconSize,
color: Colors.black,
onButtonCreated: _onButtonCreated,
onSessionStarted: _onSessionStarted,
onSessionEnded: () => setState(() => _state = AppState.idle),
onRequestCompleted: _onRequestCompleted,
onRequestFailed: _onRequestFailed,
),
],
),
body: Center(child: _handleState()),
);
}
Widget _handleState() {
switch (_state) {
case AppState.idle:
return Text('ChromeCast not connected');
case AppState.connected:
return Text('No media loaded');
case AppState.mediaLoaded:
return _mediaControls();
case AppState.error:
return Text('An error has occurred');
default:
return Container();
}
}
Widget _mediaControls() {
return Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
_RoundIconButton(
icon: Icons.replay_10,
onPressed: () => _controller.seek(relative: true, interval: -10.0),
),
_RoundIconButton(
icon: _playing! ? Icons.pause : Icons.play_arrow,
onPressed: _playPause),
_RoundIconButton(
icon: Icons.forward_10,
onPressed: () => _controller.seek(relative: true, interval: 10.0),
)
],
);
}
Future<void> _playPause() async {
final playing = await (_controller.isPlaying() as Future<bool>);
if (playing) {
await _controller.pause();
} else {
await _controller.play();
}
setState(() => _playing = !playing);
}
Future<void> _onButtonCreated(ChromeCastController controller) async {
_controller = controller;
print('Button Made');
await _controller.addSessionListener();
}
Future<void> _onSessionStarted() async {
setState(() => _state = AppState.connected);
await _controller.loadMedia(
'https://commondatastorage.googleapis.com/gtv-videos-bucket/sample/BigBuckBunny.mp4');
}
Future<void> _onRequestCompleted() async {
final playing = await _controller.isPlaying();
setState(() {
_state = AppState.mediaLoaded;
_playing = playing;
});
}
Future<void> _onRequestFailed(String? error) async {
setState(() => _state = AppState.error);
print(error);
}
}
class _RoundIconButton extends StatelessWidget {
final IconData icon;
final VoidCallback onPressed;
_RoundIconButton({required this.icon, required this.onPressed});
[@override](/user/override)
Widget build(BuildContext context) {
return RaisedButton(
child: Icon(icon, color: Colors.white),
padding: EdgeInsets.all(16.0),
color: Colors.blue,
shape: CircleBorder(),
onPressed: onPressed);
}
}
enum AppState { idle, connected, mediaLoaded, error }
更多关于Flutter视频投射插件flutter_video_cast_v2的使用的实战教程也可以访问 https://www.itying.com/category-92-b0.html
更多关于Flutter视频投射插件flutter_video_cast_v2的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html
当然,以下是一个关于如何使用 flutter_video_cast_v2
插件的示例代码。这个插件允许你将 Flutter 应用中的视频投射到支持 DLNA 或 Chromecast 的设备上。
首先,确保你已经在 pubspec.yaml
文件中添加了依赖:
dependencies:
flutter:
sdk: flutter
flutter_video_cast_v2: ^x.y.z # 请替换为最新版本号
然后运行 flutter pub get
来安装依赖。
接下来,你需要进行一些初始化设置,并在你的应用中实现视频投射功能。以下是一个简单的示例:
主应用代码 (main.dart)
import 'package:flutter/material.dart';
import 'package:flutter_video_cast_v2/flutter_video_cast_v2.dart';
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Video Cast Example',
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: VideoCastScreen(),
);
}
}
class VideoCastScreen extends StatefulWidget {
@override
_VideoCastScreenState createState() => _VideoCastScreenState();
}
class _VideoCastScreenState extends State<VideoCastScreen> {
late VideoCastManager _castManager;
late bool _isCasting;
@override
void initState() {
super.initState();
_castManager = VideoCastManager();
_isCasting = false;
// 监听连接状态变化
_castManager.deviceManager.addListener(() {
setState(() {});
});
// 初始化设备扫描
_castManager.initialize();
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('Flutter Video Cast Example'),
),
body: Padding(
padding: const EdgeInsets.all(16.0),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
'Casting Status: $_isCasting',
style: TextStyle(fontSize: 18),
),
SizedBox(height: 20),
ElevatedButton(
onPressed: () async {
// 扫描可用设备
await _castManager.deviceManager.scanForDevices();
final devices = _castManager.deviceManager.devices;
if (devices.isNotEmpty) {
// 选择第一个设备
final device = devices.first;
// 连接到设备
await _castManager.connectToDevice(device);
// 开始投射视频
await _castManager.loadMedia(
'https://www.example.com/path/to/your/video.mp4',
metaData: MediaMetadata(
title: 'Video Title',
subtitle: 'Video Subtitle',
images: [
MediaImage(
url: 'https://www.example.com/path/to/your/thumbnail.jpg',
),
],
),
);
setState(() {
_isCasting = true;
});
} else {
ScaffoldMessenger.of(context).showSnackBar(
SnackBar(content: Text('No devices found')),
);
}
},
child: Text('Start Casting'),
),
SizedBox(height: 20),
if (_isCasting)
ElevatedButton(
onPressed: () async {
await _castManager.disconnect();
setState(() {
_isCasting = false;
});
},
child: Text('Stop Casting'),
),
],
),
),
);
}
@override
void dispose() {
_castManager.dispose();
super.dispose();
}
}
说明
- 初始化
VideoCastManager
:在initState
方法中初始化VideoCastManager
并开始扫描设备。 - 监听设备变化:通过监听
deviceManager
的变化来更新 UI。 - 扫描设备:使用
scanForDevices
方法扫描可用的投射设备。 - 连接到设备:选择设备并使用
connectToDevice
方法连接到该设备。 - 加载媒体:使用
loadMedia
方法加载视频 URL 和元数据。 - 停止投射:在投射状态下,提供一个按钮来调用
disconnect
方法停止投射。
请确保替换示例中的视频 URL 和缩略图 URL 为实际有效的资源。这个示例代码展示了基本的视频投射流程,包括初始化、扫描设备、连接到设备、加载媒体和停止投射。
希望这对你有所帮助!如果有其他问题,请随时询问。