flutter开发实战-video_player视频播放功能及视频缓存

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 cacheFuture<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处理视频缓存。

学习记录,每天不停进步。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/77896.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

代码分析:循环创建N个子进程——为什么最后一个属于父进程?

黑马C/C 2018年32期代码分析 //循环创建n个子进程 #include <stdio.h> #include <stdlib.h> #include <string.h> #include <sys/types.h> #include <unistd.h>int main() {int i 0;for(i0; i<3; i){//创建子进程pid_t pid fork();if(pid&…

EMD经验模态分解介绍

EMD概述 其实一种信号分解方法&#xff0c;是一种自适应的数据处理方法&#xff0c;适合非线性和非平稳时间序列的分析和研究&#xff0c;其本质是对数据序列或信号的平稳化处理。 将上面6个信号叠加如下&#xff1a; 就是6个简单信号叠加&#xff0c;形成一个复杂信号。 核心…

关于 Ubuntu 长按 shift 无效, 按 Esc 直接进入 grub 改密码的解决方法

本次长按shift没有反应&#xff0c;直接进入了系统界面&#xff0c;所以改用长按Esc键&#xff0c;步骤如下&#xff1a; 1. 长按esc&#xff0c;进入grub>提示 2.输入grub>normal &#xff0c;回车 3.上一步回车后&#xff0c;继续敲击Esc &#xff0c;出现grub界面 …

2023.08.01 驱动开发day8

驱动层 #include <linux/init.h> #include <linux/module.h> #include <linux/of.h> #include <linux/of_irq.h> #include <linux/interrupt.h> #include <linux/fs.h> #include <linux/gpio.h> #include <linux/of_gpio.h>#…

嵌入式开发学习(STC51-7-矩阵按键)

内容 按下S1-S16键&#xff0c;对应数码管最左边显示0-F 矩阵按键简介 独立按键与单片机连接时&#xff0c;每一个按键都需要单片机的一个I/O 口&#xff0c;若某单片机系统需较多按键&#xff0c;如果用独立按键便会占用过多的I/O口资源&#xff1b;而单片机 系统中I/O口资…

【网络编程·传输层】UDP和TCP的报头

目录 一、端口号划分 二、部分指令 1、pidof&#xff08;用于查看进程id&#xff09; 2、netstat&#xff08;查看网络状态&#xff09; 三、UDP协议 1、UDP协议格式 2、UDP协议如何进行封装、解包、分用 2.1封装、解包 2.2分用 3、UDP协议的特点 3.1UDP协议的特点 …

装饰器模式(C++)

定义 动态(组合)地给一个对象增加一些额外的职责。就增加功能而言&#xff0c;Decorator模式比生成子类(继承)更为灵活(消除重复代码&减少子类个数)。 一《设计模式》 GoF 装饰器模式&#xff08;Decorator Pattern&#xff09;允许向一个现有的对象添加新的功能&#xf…

【深度学习环境】安装anaconda、tensorflow、pycharm

目录 1.安装anaconda 2.安装tensorflow-gpu 3.安装pycharm 4.VNC操作 5.安装Pytorch PS: linux下常见的操作&#xff1a; 1.Linux下强制关闭程序&#xff1a; 2.导出环境 2.1.pip导出 2.2.conda导出 2.3.其他 3.windows下的环境安装 & pycharm远程配置 4.bash…

PostgreSQL Patroni_exporter 监控 patroni高可用工具

Patroni是Cybertec公司基于python语言开发的&#xff0c;可用于使用流复制来创建&#xff0c;管理&#xff0c;维护和监视高可用性PostgreSQL集群设置的工具。 目前&#xff0c;PatroniEtcd 是最为推荐的PostgreSQL数据库高可用方案之一。 PostgreSQL有postgres_exporter监控采…

人工智能学习07--pytorch23--目标检测:Deformable-DETR训练自己的数据集

参考 https://blog.csdn.net/qq_44808827/article/details/125326909https://blog.csdn.net/dystsp/article/details/125949720?utm_mediumdistribute.pc_relevant.none-task-blog-2~default~baidujs_baidulandingword~default-0-125949720-blog-125326909.235^v38^pc_releva…

《吐血整理》进阶系列教程-拿捏Fiddler抓包教程(18)-Fiddler如何接口测试,妈妈再也不担心我不会接口测试了

1.简介 Fiddler最大的优势在于抓包&#xff0c;我们大部分使用的功能也在抓包的功能上&#xff0c;fiddler做接口测试也是非常方便的。 领导或者开发给你安排接口测试的工作任务&#xff0c;但是没有给你接口文档&#xff08;由于开发周期没有时间出接口文档&#xff09;&…

ProgressBar基本使用

作用&#xff1a;进度条&#xff0c;用于展示某个任务的完成情况&#xff0c; 常用属性&#xff1a; 设定进度条的最大、最小值、自增步长 常用事件&#xff1a; 后台代码&#xff1a; private void progressBar1_Click(object sender, EventArgs e){Thread t;//使用线程执行…

TabR:检索增强能否让深度学习在表格数据上超过梯度增强模型?

这是一篇7月新发布的论文&#xff0c;他提出了使用自然语言处理的检索增强Retrieval Augmented技术&#xff0c;目的是让深度学习在表格数据上超过梯度增强模型。 检索增强一直是NLP中研究的一个方向&#xff0c;但是引入了检索增强的表格深度学习模型在当前实现与非基于检索的…

uniapp:图片验证码检验问题处理

图形验证码功能实现 uniapp&#xff1a;解决图形验证码问题及利用arraybuffer二进制转base64格式图片&#xff08;后端传的图片数据形式&#xff1a;x00\x10JFIF\x00\x01\x02\x00…&#xff09;_❆VE❆的博客-CSDN博客 UI稿&#xff1a; 需求&#xff1a;向后端请求验证码图片&…

03 制作Ubuntu启动盘

1 软碟通 我是用软碟通制作启动盘。安装软碟通时一定要把虚拟光驱给勾选上&#xff0c;其余两个可以看你心情。 2 镜像文件 我使用清华镜像网站找到的Ubuntu镜像文件。 Index of /ubuntu-releases/ | 清华大学开源软件镜像站 | Tsinghua Open Source Mirror 请自己选择镜像…

IOS看书最终选择|源阅读转换|开源阅读|IOS自签

环境&#xff1a;IOS想使用 换源阅读 问题&#xff1a;换新手机&#xff0c;源阅读下架后&#xff0c;没有好的APP阅读小说 解决办法&#xff1a;自签APP 转换源仓库书源 最终预览 &#xff1a;https://rc.real9.cn/ 背景&#xff1a;自从我换了新iPhone手机&#xff0c;就无法…

C# Blazor 学习笔记(10):依赖注入

文章目录 前言Blazor 依赖注入依赖注入用于解决什么问题&#xff1f;依赖注入的生命周期。测试代码 总结补充日期2023年8月4日 前言 Blazor 具有前后端不分离模式&#xff0c;但是如何直接调用需要一定的设置 Blazor 依赖注入 依赖注入在spring里面很常见&#xff0c;毕竟.N…

Gof23设计模式之组合模式

1.定义 ​组合模式又名部分整体模式&#xff0c;是用于把一组相似的对象当作一个单一的对象。组合模式依据树形结构来组合对象&#xff0c;用来表示部分以及整体层次。这种类型的设计模式属于结构型模式&#xff0c;它创建了对象组的树形结构。 2.结构 组合模式主要包含三种…

ChatGPT-4.0:你准备好了吗?

3202年了&#xff0c;你还在用ChatGPT 3.5吗&#xff1f; 来感受一下ChatGPT 4.0的魅力吧 文末附升级链接 1、颠倒黑白&#xff1f; 2、解读幽默&#xff1f; 3、小镇做题家&#xff1f; 如何白嫖&#xff1f; 最后 1、科技的发展加快了知识更新的速度&#xff0c;唯有终身…

(四)Node.js - npm与包

1. 什么是包 Node.js中的第三方模块又叫做包。 不同于Node.js中的内置模块与自定义模块&#xff0c;包是由第三方个人或团队开发出来的&#xff0c;免费供所有人使用。 由于Node.js的内置模块进提供了一些底层的API&#xff0c;导致在基于内置模块进行项目开发时&#xff0c…