Flutter视频下载插件awesome_video_downloader的使用
Flutter视频下载插件awesome_video_downloader的使用
简介
awesome_video_downloader
是一个Flutter插件,用于下载各种格式(HLS、DASH、MP4)的视频,并支持后台下载、进度跟踪和离线播放。
特性
- 支持多种视频格式:HLS、DASH、MP4等。
- 并发下载。
- 暂停、恢复和取消下载。
- 实时进度跟踪。
- 后台下载支持。
- 跨平台(iOS & Android)。
- 自适应流的质量选择。
- 离线播放支持。
入门指南
安装
在你的 pubspec.yaml
文件中添加以下依赖:
dependencies:
awesome_video_downloader: ^1.0.0
平台设置
iOS
在 Info.plist
中添加以下键值:
<key>UIBackgroundModes</key>
<array>
<string>audio</string>
<string>fetch</string>
</array>
Android
在 AndroidManifest.xml
中添加以下权限:
<uses-permission android:name="android.permission.INTERNET"/>
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
<uses-permission android:name="android.permission.FOREGROUND_SERVICE"/>
使用方法
基本下载
final downloader = AwesomeVideoDownloader();
await downloader.initialize();
// 开始下载
final downloadId = await downloader.startDownload(
url: 'https://example.com/video.mp4',
fileName: 'my_video.mp4',
format: 'mp4',
);
// 监控进度
downloader.getDownloadProgress(downloadId).listen(
(progress) {
print('Progress: ${progress.formattedProgress}');
print('Speed: ${progress.formattedSpeed}');
print('Downloaded: ${progress.formattedSize}');
if (progress.isCompleted) {
print('Download completed! File at: ${progress.filePath}');
}
},
onError: (error) => print('Download error: $error'),
);
带选项的下载
final downloadId = await downloader.startDownload(
url: 'https://example.com/stream.m3u8',
fileName: 'video.mp4',
format: 'hls',
options: VideoDownloadOptions(
minimumBitrate: 1500000, // 1.5 Mbps
maximumBitrate: 4000000, // 4 Mbps
preferHDR: true,
preferMultichannel: true,
headers: {
'Authorization': 'Bearer token123',
},
),
);
管理下载
// 暂停下载
await downloader.pauseDownload(downloadId);
// 恢复下载
await downloader.resumeDownload(downloadId);
// 取消下载
await downloader.cancelDownload(downloadId);
// 获取所有下载
final downloads = await downloader.getAllDownloads();
for (final download in downloads) {
print('${download.fileName}: ${download.state.name}');
}
下载状态
下载可以处于以下状态:
notStarted
: 下载尚未开始downloading
: 下载进行中paused
: 下载已暂停completed
: 下载已完成failed
: 下载失败cancelled
: 下载已取消
示例应用
以下是一个完整的示例应用程序,展示如何使用 awesome_video_downloader
插件:
import 'dart:async';
import 'package:flutter/material.dart';
import 'package:awesome_video_downloader/awesome_video_downloader.dart';
void main() {
runApp(const MyApp());
}
class MyApp extends StatelessWidget {
const MyApp({super.key});
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Video Downloader Demo',
theme: ThemeData(
colorScheme: ColorScheme.fromSeed(seedColor: Colors.blue),
useMaterial3: true,
),
home: const DownloaderPage(),
);
}
}
class DownloaderPage extends StatefulWidget {
const DownloaderPage({super.key});
@override
State<DownloaderPage> createState() => _DownloaderPageState();
}
class _DownloaderPageState extends State<DownloaderPage> {
final _downloader = AwesomeVideoDownloader();
final _urlController = TextEditingController();
final Map<String, StreamSubscription<DownloadProgress>> _progressSubscriptions = {};
List<DownloadInfo> _downloads = [];
@override
void initState() {
super.initState();
_initializeDownloader();
}
Future<void> _initializeDownloader() async {
try {
await _downloader.initialize();
_loadDownloads();
} catch (e) {
if (mounted) {
ScaffoldMessenger.of(context).showSnackBar(
SnackBar(content: Text('Failed to initialize downloader: $e')),
);
}
}
}
Future<void> _loadDownloads() async {
_downloads = await _downloader.getAllDownloads();
setState(() {});
for (var download in _downloads) {
if (download.isDownloading) {
_subscribeToProgress(download.id);
}
}
}
void _subscribeToProgress(String downloadId) {
_progressSubscriptions[downloadId]?.cancel();
_progressSubscriptions[downloadId] =
_downloader.getDownloadProgress(downloadId).listen(
(progress) {
setState(() {
final index = _downloads.indexWhere((d) => d.id == downloadId);
if (index != -1) {
_downloads[index] = _downloads[index].copyWith(
bytesDownloaded: progress.bytesDownloaded,
totalBytes: progress.totalBytes,
state: progress.state,
filePath: progress.filePath,
);
if (progress.isCompleted) {
_progressSubscriptions[downloadId]?.cancel();
_progressSubscriptions.remove(downloadId);
ScaffoldMessenger.of(context).showSnackBar(
SnackBar(
content: Text('Download completed: ${_downloads[index].fileName}'),
action: progress.filePath != null
? SnackBarAction(
label: 'Show File',
onPressed: () {
// TODO: Implement file viewing
},
)
: null,
),
);
}
}
});
},
onError: (error) {
setState(() {
final index = _downloads.indexWhere((d) => d.id == downloadId);
if (index != -1) {
_downloads[index] = _downloads[index].copyWith(
state: DownloadState.failed,
);
}
});
_progressSubscriptions[downloadId]?.cancel();
_progressSubscriptions.remove(downloadId);
},
);
}
Future<void> _startDownload() async {
if (_urlController.text.isEmpty) return;
final url = _urlController.text;
final uri = Uri.parse(url);
final fileName = uri.pathSegments.last;
try {
final downloadId = await _downloader.startDownload(
url: url,
fileName: fileName,
format: _getFormat(url),
options: VideoDownloadOptions(
preferHDR: true,
preferMultichannel: true,
),
);
_subscribeToProgress(downloadId);
_loadDownloads();
_urlController.clear();
} catch (e) {
if (mounted) {
ScaffoldMessenger.of(context).showSnackBar(
SnackBar(content: Text('Failed to start download: $e')),
);
}
}
}
String _getFormat(String url) {
if (url.contains('.m3u8')) return 'hls';
if (url.contains('.mpd')) return 'dash';
return 'mp4';
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text('Video Downloader'),
backgroundColor: Theme.of(context).colorScheme.inversePrimary,
),
body: Column(
children: [
Padding(
padding: const EdgeInsets.all(16.0),
child: Row(
children: [
Expanded(
child: TextField(
controller: _urlController,
decoration: const InputDecoration(
hintText: 'Enter video URL',
border: OutlineInputBorder(),
),
),
),
const SizedBox(width: 16),
FilledButton(
onPressed: _startDownload,
child: const Text('Download'),
),
],
),
),
Expanded(
child: ListView.builder(
itemCount: _downloads.length,
itemBuilder: (context, index) {
final download = _downloads[index];
return DownloadListItem(
download: download,
onPause: () async {
await _downloader.pauseDownload(download.id);
_loadDownloads();
},
onResume: () async {
await _downloader.resumeDownload(download.id);
_subscribeToProgress(download.id);
_loadDownloads();
},
onCancel: () async {
await _downloader.cancelDownload(download.id);
_progressSubscriptions[download.id]?.cancel();
_progressSubscriptions.remove(download.id);
_loadDownloads();
},
);
},
),
),
],
),
);
}
@override
void dispose() {
for (var subscription in _progressSubscriptions.values) {
subscription.cancel();
}
_urlController.dispose();
super.dispose();
}
}
class DownloadListItem extends StatelessWidget {
final DownloadInfo download;
final VoidCallback onPause;
final VoidCallback onResume;
final VoidCallback onCancel;
const DownloadListItem({
super.key,
required this.download,
required this.onPause,
required this.onResume,
required this.onCancel,
});
@override
Widget build(BuildContext context) {
return Card(
margin: const EdgeInsets.symmetric(horizontal: 16, vertical: 8),
child: Padding(
padding: const EdgeInsets.all(16),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
download.fileName,
style: Theme.of(context).textTheme.titleMedium,
),
const SizedBox(height: 8),
if (download.isDownloading) ...[
LinearProgressIndicator(
value: download.progress,
),
const SizedBox(height: 8),
Text(download.formattedSize),
] else
Text('Status: ${download.state.name}'),
if (download.filePath != null)
Text('Saved at: ${download.filePath}',
style: Theme.of(context).textTheme.bodySmall),
const SizedBox(height: 8),
Row(
mainAxisAlignment: MainAxisAlignment.end,
children: [
if (download.isDownloading)
IconButton.filledTonal(
icon: const Icon(Icons.pause),
onPressed: onPause,
)
else if (download.isPaused)
IconButton.filledTonal(
icon: const Icon(Icons.play_arrow),
onPressed: onResume,
),
const SizedBox(width: 8),
IconButton.filledTonal(
icon: const Icon(Icons.cancel),
onPressed: onCancel,
),
],
),
],
),
),
);
}
}
通过上述代码,您可以轻松地实现视频下载功能,并根据需要管理下载任务。希望这些信息对您有所帮助!
更多关于Flutter视频下载插件awesome_video_downloader的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html
更多关于Flutter视频下载插件awesome_video_downloader的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html
当然,下面是一个关于如何使用Flutter视频下载插件awesome_video_downloader
的示例代码。这个插件允许你在Flutter应用中下载视频文件。
首先,确保你已经在pubspec.yaml
文件中添加了awesome_video_downloader
依赖:
dependencies:
flutter:
sdk: flutter
awesome_video_downloader: ^x.y.z # 替换为最新版本号
然后,运行flutter pub get
来安装依赖。
接下来,在你的Flutter应用中,你可以使用以下代码来下载视频:
import 'package:flutter/material.dart';
import 'package:awesome_video_downloader/awesome_video_downloader.dart';
import 'package:path_provider/path_provider.dart';
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Video Downloader Demo',
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: MyHomePage(),
);
}
}
class MyHomePage extends StatefulWidget {
@override
_MyHomePageState createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
String _downloadStatus = 'Not started';
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('Flutter Video Downloader Demo'),
),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Text(
'Download Status: $_downloadStatus',
style: TextStyle(fontSize: 20),
),
SizedBox(height: 20),
ElevatedButton(
onPressed: _downloadVideo,
child: Text('Download Video'),
),
],
),
),
);
}
Future<void> _downloadVideo() async {
setState(() {
_downloadStatus = 'Downloading...';
});
// 获取应用存储目录
final Directory appDocDir = await getApplicationDocumentsDirectory();
String appDocPath = appDocDir.path;
// 视频URL(替换为你想要下载的视频URL)
String videoUrl = 'https://www.example.com/path/to/your/video.mp4';
// 设置下载路径
String downloadPath = '$appDocPath/video.mp4';
// 创建下载任务
var downloader = VideoDownloader();
try {
var downloadId = await downloader.downloadFile(
videoUrl,
downloadPath,
);
// 检查下载状态(这里简单处理,实际应用中可能需要更复杂的状态管理)
var status = await downloader.getDownloadStatus(downloadId);
while (status.status != DownloadTaskStatus.complete) {
setState(() {
_downloadStatus = 'Downloaded: ${status.progressInPercent}%';
});
await Future.delayed(Duration(seconds: 1)); // 每秒更新一次进度
status = await downloader.getDownloadStatus(downloadId);
}
setState(() {
_downloadStatus = 'Download Complete!';
});
} catch (e) {
setState(() {
_downloadStatus = 'Download Failed: ${e.message}';
});
}
}
}
在这个示例中,我们创建了一个简单的Flutter应用,其中包含一个按钮用于启动视频下载任务。下载任务完成后,下载状态将更新为“Download Complete!”。如果下载失败,则会显示错误信息。
请注意:
videoUrl
需要替换为你想要下载的实际视频URL。- 在实际应用中,你可能需要更复杂的错误处理和状态管理。
awesome_video_downloader
插件的API可能会有所变化,请参考最新的文档以获取最新信息。