flutter开发实战-video_player视频播放功能及视频缓存
最近开发过程中video_player播放视频,
一、引入video_player
在pubspec.yaml引入video_player
video_player: ^2.7.0
在iOS上,video_player使用的是AVPlayer进行播放。
在Android上,video_player使用的是ExoPlayer。
二、使用前设置
2.1 在iOS中的设置
在iOS工程中info.plist添加一下设置,以便支持Https,HTTP的视频地址
<key>NSAppTransportSecurity</key>
<dict>
<key>NSAllowsArbitraryLoads</key>
<true/>
</dict>
2.2 在Android中的设置
需要在/android/app/src/main/AndroidManifest.xml文件中添加网络权限
<uses-permission android:name="android.permission.INTERNET"/>
三、使用前设置video_player
video_player 使用VideoPlayerController来控制播放与暂停
VideoPlayerController的初始化
_controller = VideoPlayerController.networkUrl(Uri.parse(
'https://flutter.github.io/assets-for-api-docs/assets/videos/bee.mp4'))
..initialize().then((_) {
// Ensure the first frame is shown after the video is initialized, even before the play button has been pressed.
setState(() {});
});
显示视频Widget
Center(
child: _controller.value.isInitialized
? AspectRatio(
aspectRatio: _controller.value.aspectRatio,
child: VideoPlayer(_controller),
)
: Container(),
),
控制播放与暂停
// 播放
_controller.play();
// 暂停
_controller.pause();
完整实例代码
import 'package:flutter/material.dart';
import 'package:video_player/video_player.dart';
void main() => runApp(const VideoApp());
/// Stateful widget to fetch and then display video content.
class VideoApp extends StatefulWidget {
const VideoApp({super.key});
_VideoAppState createState() => _VideoAppState();
}
class _VideoAppState extends State<VideoApp> {
late VideoPlayerController _controller;
void initState() {
super.initState();
_controller = VideoPlayerController.networkUrl(Uri.parse(
'https://flutter.github.io/assets-for-api-docs/assets/videos/bee.mp4'))
..initialize().then((_) {
// Ensure the first frame is shown after the video is initialized, even before the play button has been pressed.
setState(() {});
});
}
Widget build(BuildContext context) {
return MaterialApp(
title: 'Video Demo',
home: Scaffold(
body: Center(
child: _controller.value.isInitialized
? AspectRatio(
aspectRatio: _controller.value.aspectRatio,
child: VideoPlayer(_controller),
)
: Container(),
),
floatingActionButton: FloatingActionButton(
onPressed: () {
setState(() {
_controller.value.isPlaying
? _controller.pause()
: _controller.play();
});
},
child: Icon(
_controller.value.isPlaying ? Icons.pause : Icons.play_arrow,
),
),
),
);
}
void dispose() {
super.dispose();
_controller.dispose();
}
}
注意:video_player暂时不支持缓存,如果需要可以使用flutter_cache_manager
四 缓存flutter_cache_manager下载文件
使用flutter_cache_manager代码如下
import 'package:flutter_cache_manager/flutter_cache_manager.dart';
import 'dart:async';
import 'dart:typed_data';
import 'package:file/file.dart';
import 'package:flutter_suprisebox/utils/string_utils.dart';
class CustomCacheManager {
static const key = 'customCacheKey';
static CacheManager instance = CacheManager(
Config(
key,
stalePeriod: const Duration(days: 7),
maxNrOfCacheObjects: 20,
repo: JsonCacheInfoRepository(databaseName: key),
fileService: HttpFileService(),
),
);
Future<File> getSingleFile(
String url, {
String? key,
Map<String, String>? headers,
}) async {
return await instance.getSingleFile(url, key: key, headers: headers);
}
Future<FileInfo?> getFileFromCache(String url,
{bool ignoreMemCache = false}) async {
String? key = StringUtils.toMD5(url);
if (key != null && key.isNotEmpty) {
return await instance.getFileFromCache(key, ignoreMemCache: ignoreMemCache);
}
return null;
}
Future<FileInfo> downloadFile(String url,
{String? key,
Map<String, String>? authHeaders,
bool force = false}) async {
return await instance.downloadFile(url, key: key, authHeaders: authHeaders, force: force);
}
Stream<FileResponse> getFileStream(String url,
{String? key, Map<String, String>? headers, bool withProgress = false}) {
return instance.getFileStream(url,
key: key, headers: headers, withProgress: withProgress);
}
Future<void> removeFile(String key) async {
return instance.removeFile(key);
}
/// Removes all files from the cache
Future<void> emptyCache() {
return instance.emptyCache();
}
}
添加flutter_cache_manager后,flutter_cache_manager会先判断文件是否存在,如果不存在则下载视频文件。
使用CustomCacheManager后的视频初始化代码如下
Future<void> stuVideoPlay() async {
_controller?.dispose();
if (Platform.isIOS) {
_controller = VideoPlayerController.network(widget.videoUrl);
} else {
FileInfo? fileInfo =
await CustomCacheManager().getFileFromCache(widget.videoUrl);
if (fileInfo == null) {
fileInfo = await CustomCacheManager().downloadFile(widget.videoUrl);
// if (fileInfo != null) {
_controller = VideoPlayerController.file(fileInfo.file);
// } else {
// _controller = VideoPlayerController.network(widget.videoUrl);
// }
} else {
var file = await CustomCacheManager().getSingleFile(widget.videoUrl);
_controller = VideoPlayerController.file(file);
}
}
await _controller?.initialize().then((_) {
// Ensure the first frame is shown after the video is initialized, even before the play button has been pressed.
setState(() {});
});
await _controller!.setLooping(true);
if (widget.autoPlay) {
await _controller?.play();
} else {
await _controller?.pause();
}
}
特别注意:我使用的时候,flutter_cache_manager好像暂时不支持iOS。这点可能还需要其他方案来做缓存处理。如果支持了请留言哦,也可能我记错了。
四、小结
flutter开发实战-video_player视频播放功能及视频缓存。video_player播放视频,flutter_cache_manager处理视频缓存。
学习记录,每天不停进步。