前言

什么是VideoView?

VideoView是Android原生提供的一个封装类,只用以播放视频,视频源可以是本地也可以是网络,支持大部分格式的视频源。

VideoView原理

VideoView继承自SurfaceView,里面封装了一个MediaPlayer用以具体的播放业务,并自带了一个简单的控制界面MediaController。

适用场景

VideoView的功能比较简单,非常适用于那些只单纯地播放视频的场景,如不断循环播放的广告视频。不适用于交互性多的视频播放场景,像调节亮度、调节音量、双击暂停等交互逻辑,VideoView是无法实现的。

1.简单使用步骤

第一步:在布局中添加

<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"xmlns:app="http://schemas.android.com/apk/res-auto"xmlns:tools="http://schemas.android.com/tools"android:layout_width="match_parent"android:layout_height="match_parent"tools:context=".MainActivity"><VideoViewandroid:id="@+id/vv_main"android:layout_width="match_parent"android:layout_height="wrap_content"app:layout_constraintStart_toStartOf="parent"app:layout_constraintTop_toTopOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>

第二步:设置视频源地址并开始播放

//播放本地视频String videoPath= Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_MOVIES)+"/dync.mp4";//videoPath = "http://vfx.mtime.cn/Video/2019/07/12/mp4/190712140656051701.mp4";//设置播放地址,网络视频同样使用此方法,将网址链接放入即可
vvMain.setVideoPath(videoPath);
//开始播放
vvMain.start();

注意:本地视频需要读取存储的权限,网络视频需要网络权限,别忘了添加。

<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>
<uses-permission android:name="android.permission.INTERNET"/>

简单两步即可实现播放视频,很轻松就能实现视频的播放,这也是VideoView的方便之处。

2.开启视频控制栏

上述VideoView播放视频的方式是没法对其进行任何控制的,如要停止也只能等它播放完毕,VideoView中提供了一个简单的控制栏,具有以下功能。

  • 播放/暂停
  • 查看视频长度与当前位置
  • 进度条拖动
  • 快进15秒
  • 快退5秒

界面如下

这个控制栏默认是不开启的,如要将之打开,则需要设置MediaController,然后点击视频区域即可弹出此界面。如果视频没有播放或是调用停止方法如stopPlayaback()suspend(),那么此控制栏将不会弹出,调用pause()不影响弹出。

 MediaController mediaController = new MediaController(this);
vvMain.setMediaController(mediaController);

此处的context一定要传入activity,否则在点击视频区域时程序会崩溃,报如下错误。

android.view.WindowManager$BadTokenException: Unable to add window -- token null is not valid; is your activity running?

意思是无法将视图添加到window中,因为context不是Activity无法attch Window。

2.1 显示上下首的按钮

如果我想切换到下一个或上一个视频该怎么办,上述界面中并没有这两个按钮啊!难道要自己再添加两个这样的Button,那我还不如自己实现这个控制栏呢。

莫慌,其实MediaController是有这上一首和下一首的按钮的,只不过默认将它隐藏了,只要给他设置个监听方法就可以将之显示出来了。

 mediaController.setPrevNextListeners(new View.OnClickListener() {@Overridepublic void onClick(View v) {//下一首,实现具体的切换逻辑}}, new View.OnClickListener() {@Overridepublic void onClick(View v) {//上一首}});

就算你设置了两个null,也能将之显示出来,只不过点击按钮没有反应罢了。具体要播放哪个视频,就需要自己维护一个播放列表了。

效果如下图。

2.2 控制栏的显示时间

当点击视频区域控制栏会弹出,过一段时间后会自动隐藏,这个时间是多少呢?
3秒
这是默认时间,由MediaController类控制。

private static final int sDefaultTimeout = 3000;

这个时间用是无法更改的,除非不用VideoView,而是使用另一种视频播放方式MediaPlayer+SurfaceView+MediaController在点击事件中自己实现显示逻辑。可参考此篇文章!

3.视频的状态获取与控制

VidewView的可调用方法由两部分组成,一是MediaPlayerControl接口规范,二是它自身实现的方法。

3.1 MediaPlayerControl接口提供的方法

方法 用途
void start(); 开始播放视频
void pause(); 暂停播放视频
int getDuration(); 获取视频总长度,毫秒值
int getCurrentPosition(); 获取当前播放位置,毫秒值
void seekTo(int pos); 指定播放某个位置
boolean isPlaying(); 视频是否在播放
int getBufferPercentage(); 获取缓冲进度,网络视频中使用
boolean canPause(); 能否暂停
boolean canSeekBackward(); 能否快退
boolean canSeekForward(); 能否快进
int getAudioSessionId(); 获取音频会话ID

3.2 VideoView自身实现的方法

方法 用途
void resume(); 重新播放视频
void stopPlayaback(); 停止播放视频
void suspend(); 停止播放
void setOnPreparedListener(MediaPlayer.OnPreparedListener l); 视频加载状态的监听
void setOnInfoListener(OnInfoListener l); 视频信息的监听,只有播放时才会调用此监听
void setOnCompletionListener(OnCompletionListener l); 视频播放完毕的监听
void setOnErrorListener(OnErrorListener l); 视频加载或播放异常的监听

4.视频监听器实用技巧

4.1 让视频开始播放的另一种方式

前面说到只需要调用VideoView的start()方法即可完成视频播放的设置,当视频内容加载至内存完成后即会自动开始播放,其实调用VideoView的start方法并不是直接让MediaPlayer开始播放视频,都是需要经过准备阶段这一固定步骤的。

故可在视频的加载监听器中,调用MediaPlayer的start()方法开始视频的播放,效果与VideoView调用start()方法一致。

    vvMain.setOnPreparedListener(new MediaPlayer.OnPreparedListener() {@Overridepublic void onPrepared(MediaPlayer mp) {mp.start();}});

当VideoView调用setVideoPath()方法时就会开始加载视频内容至内存中,调用的是

 mMediaPlayer.prepareAsync();

所以VideoView的加载过程是一个异步加载。

4.2 实现视频循环播放

一般对于广告视频而言,其必定是不断地循环播放的,而VideoView也可以通过两种方式来达到循环播放的效果。

方式一:通过MediaPlayer方法
mp.setLooping(true);

此方法可用在OnPreparedListener加载回调和OnInfoListener视频信息回调,但不能用在OnCompletionListener播放完毕的回调中,在播放完毕时再调用此方法并不会让视频循环播放。

还有,设置了视频循环播放后,下一轮的播放不会再触发OnPreparedListenerOnInfoListener,但一样会触发在OnCompletionListener和异常回调。

方式二:在播放完毕的回调中,再次开始播放
 vvMain.setOnCompletionListener(new MediaPlayer.OnCompletionListener() {@Overridepublic void onCompletion(MediaPlayer mp) {mp.start();//也可调用videoview的start,效果是一样//vvMain.start();//调用resume方法可使视频重复播放
//                vvMain.resume();}});

在这里有三种方式可以实现再次播放

  • MediaPlayer.start()
  • VedioView.start()
  • VedioView.resume()

这三种方式当视频重复播放时都会触发信息回调,与mp.setLooping(true)不太一样。

   vvMain.setOnInfoListener(new MediaPlayer.OnInfoListener() {@Overridepublic boolean onInfo(MediaPlayer mp, int what, int extra) {return false;}});

VedioView.resume()方法还会触发加载状态回调OnPreparedListener,所以说resume()方法其实是再一次加载了这个视频内容,然后从头开始播放,与前二种方式是有所区别,前两种方式是再次播放已经加载好的视频,所以不会再触发OnPreparedListener这个回调。

4.3 去掉视频播放异常时的弹框

当视频加载或播放出现异常时,默认是会有一个弹框的,告诉用户播放出现异常,当点击了这个按钮后,会触发播放完毕的回调OnCompletionListener,弹框示意图如下。

如果想要去掉此异常弹框,那么只需在异常回调中OnErrorListener返回true即可。

   vvMain.setOnErrorListener(new MediaPlayer.OnErrorListener() {@Overridepublic boolean onError(MediaPlayer mp, int what, int extra) {return true;}});

当取消了异常弹框后,界面不会再有提示,也不会再触发完成回调OnCompletionListener

这一篇到此结束,主要介绍了VideoView的常用使用方式,下一篇将进一步介绍VideoView的控件大小与视频源大小的关系,如何调节音量,加载过大视频时如何在界面进行缓冲提示。

VideoView从入门到入坑-上篇相关推荐

  1. Kubernetes ~ k8s 从入门到入坑。

    Kubernetes ~ k8s 从入门到入坑. 文章目录 Kubernetes ~ k8s 从入门到入坑. 1. Kubernetes 介绍. 1.1 应用部署方式演变. 1.2 kubernete ...

  2. java爬山问题,关于java:不爬山不拍照设计模式入门到入坑第一课

    作者爱谈话 明天是刚好来杭州的第二周,也是一个惬意的周五,很巧也是我的生日,将来的工作可能会很忙,还是会持续保持 sharing (原本昨天发的,然而还想欠缺欠缺就又拖了一天,哈哈.奥利给) [腾讯云 ...

  3. 【Flutter从入门到入坑】Flutter 知识体系

    学习 Flutter 需要掌握哪些知识? 终端设备越来越碎片化,需要支持的操作系统越来越多,从研发效率和维护成本综合考虑,跨平台开发一定是未来大前端的趋势,我们应该拥抱变化.而 Flutter 提供了 ...

  4. 正则表达式从入门到入坑

    正则表达式从入门到入坑 入坑前先介绍两个辅助网站: 正则表达式测试网站:https://regex101.com 正则表达式思维导图:https://regexper.com 正则基础(入门) 1.元 ...

  5. markdown 本地链接_Markdown从入门到入坑

    给大家安利一款我最近特别喜欢的软件typora. 是什么:typora是一款用Markdown语言编写文档的软件.那么问题来了,什么是Markdown? Markdown是一个标记性语言,使用约定好的 ...

  6. dcloud从入门到入坑

    一.简介 dcloud是一个webapp云打包平台,你可以通过他扩展你的网页功能 官方叫他们的产品名字为 HTML5 Plus移动App,简称5+App,是一种基于HTML.JS.CSS编写的运行于手 ...

  7. 鸿蒙系统nas,NAS从入门到入坑:我发现了FreeNAS、My Cloud 、群晖的套路

    二是个人的影视观看习惯是先下载后播放,很少在线看.好在有朋友是网络技术方面的高手,你只要告诉他需求,准能得到一个满意的答案. 这个路由器的亮点就是支持迅雷下载,这也是首次使用能脱机下载的路由器. 插上 ...

  8. Shell 编程 ~ 从入门到入坑。

    Shell 基础. 文章目录 Shell 基础. Shell 概述. Shell 的分类. Shell 脚本的执行方式. 第一个脚本. Bash 的基本功能. 历史命令与补全. 历史命令的调用. 命令 ...

  9. Hbase从入门到入坑

    本博客已迁移至微信公众号!将不再更新 关注公众号即可获得免费学习资源,获得免费指导!!! 公众号后续将会持续更新clickhouse,sparkstreaming,flink,数仓建模,用户画像,实时 ...

最新文章

  1. Java线程状态及 wait、sleep、join、interrupt、yield等的区别
  2. 中国研究的超级系统计算机,学习电脑 - Book3 - V1.30 - 超级系统恢复
  3. java大公司后端多线程面试题最强分享
  4. java 基本数据类型及自己主动类型提升
  5. Docker+Jenkins+Git+GitLab实现DevOps
  6. 金融数据分析与挖掘实战练习2.5-2.9
  7. mysql中rm+-f_Mysql命令大全
  8. FirstApp,iphone开发学习总结1,UIview添加UIimage
  9. informatica学习1-数据仓库,ETL,数据仓库工具Informatica介绍
  10. web安全---XSS的形成原理
  11. 云计算数据中心运维管理的重点
  12. 二叉树多种遍历的时间复杂度和空间复杂度
  13. 实变函数(4)--Lebesgue积分
  14. 一个利用html5的图片裁剪功能(已解决ios压扁缩放等bug)
  15. 强一致共识算法-BFT/CFT
  16. PC微信逆向--定位sqlite3_exec和数据库句柄
  17. springboot志愿者活动报名服务系统jsp ssm maven
  18. Pentaho Data Integration(Kettle) 6.0
  19. 2020李宏毅机器学习笔记-More about Auto-encoder
  20. CentOS7 中没有显示 ip 地址

热门文章

  1. QT控件之(QLabel)中加载了图片想清除掉
  2. 47、W25Q128 存储器实验
  3. P1022 计算器的改良(落谷)
  4. python基本语法搭建以及环境-第一课-by好想
  5. 金九银十面试题之《设计模式》
  6. 那年声明理解不了定义与初始化(二)
  7. HihoCoder 1835 K-Dimensional Foil II ICPC2018 北京网络赛
  8. 第 2 篇、Linux操作基础 | Vim编辑器使用
  9. 为什么服务器一定放去机房托管?
  10. 统一资源定位符URL