最近项目中用到了很多视频播放的地方,不管是聊天发送的视频消息,还是类似内涵段子的视频列表,都会涉及这些知识,不过网上的知识都很零散,一会找缓存方法,一会找预览图片的方法,一会找视频动态修改尺寸的方法,总之找的人好烦,所以自己写一篇来记录这些知识点,也方便别人查阅

  • 获取视频首帧当预览图(MediaMetadataRetriever)

在VideoView中,如果直接设置播放路径,然后seekTo(1)当然也能产生预览效果,但是,如果VideoView较多,设置播放路径的方法会产生几个问题,设置路径后VideoView会取网上拉取视频(缓冲池大小),这样造成流量浪费,而且,多个VideoView会造成显示首帧非常非常慢,且有严重的卡顿

那如何解决这个问题,我的想法是,还是用首帧当预览图,不过我是在ImageView里面显示预览图,所以预览的时候不用VideoView了,获取预览图也是变的简单化,省流量,还快捷,下来我们了解下MediaMetadataRetriever类如何获取视频的首帧。MediaMetadataRetriever类不但可以获取视频首帧,还可以获取标题,时长,作者等信息,大家根据需要可以获取,我在这里就不一一举例,在获取到首帧后,我们做下缓存处理,以便下一次预览不用每次从网上拉取,然后用Glide加载显示

ThreadPoolUtils.execute(new Runnable() {@Overridepublic void run() {MediaMetadataRetriever retriever = new MediaMetadataRetriever();Bitmap bitmap = null;try {//这里要用FileProvider获取的Uriif (url.contains("http")) {retriever.setDataSource(url, new HashMap<String, String>());} else {retriever.setDataSource(url);}bitmap = retriever.getFrameAtTime();} catch (Exception ex) {ex.printStackTrace();} finally {try {retriever.release();} catch (RuntimeException ex) {ex.printStackTrace();}}showImageMessage(bitmap, positionTag, vv);}});

后记:其实还有一种办法来做预览显示,就是让后台将预览图处理好,然后拿到图片地址直接用Glide显示,都不用自己缓存,而且后台可以生成GIF,也可以用Glide显示,且显得高大上

预览图加载完毕后,点击预览图,然后我们可以做各种处理,如隐藏ImageView且显示VideoView,或者跳到视频播放界面等,各种加载逻辑大家可以发挥自己得想象

  • VideoView加载一个网络视频

VideoView加载视频其实很简单,我们直接看代码吧

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"android:layout_width="match_parent"android:layout_height="match_parent"android:orientation="vertical"><VideoViewandroid:id="@+id/mVideoView"android:layout_width="match_parent"android:layout_height="match_parent"/>
</LinearLayout>
/*** 香港卫视:http://live.hkstv.hk.lxdns.com/live/hks/playlist.m3u8* CCTV1高清:http://ivi.bupt.edu.cn/hls/cctv1hd.m3u8* CCTV3高清:http://ivi.bupt.edu.cn/hls/cctv3hd.m3u8* CCTV5高清:http://ivi.bupt.edu.cn/hls/cctv5hd.m3u8* CCTV5+高清:http://ivi.bupt.edu.cn/hls/cctv5phd.m3u8* CCTV6高清:http://ivi.bupt.edu.cn/hls/cctv6hd.m3u8* 苹果提供的测试源(点播):http://devimages.apple.com.edgekey.net/streaming/examples/bipbop_4x3/gear2/prog_index.m3u8*/private void initView() {String url="http://ivi.bupt.edu.cn/hls/cctv6hd.m3u8";VideoView videoView=findViewById(R.id.mVideoView);videoView.setVideoPath(url);videoView.requestFocus();videoView.start();}

这样一个网络视频就可以播放了

  • 视频控件长宽的大小调整

视频是播放出来了,怎么看都有点不和谐,大白边框太丑了,那缩小吧,一不小心缩变形了,看起来更别扭,怎么才能按照视频的比例来显示呢?我们上面不是讲过MediaMetadataRetriever吗?我们可以根据获取的首帧图片的大小确定视频的大小,MediaMetadataRetriever还可以采用

int videoWidth=retriever.METADATA_KEY_VIDEO_WIDTH;
int videoHeight=retriever.METADATA_KEY_VIDEO_HEIGHT;

来确定视频的大小。从而动态设置VideoView的大小,咦,设置那么大的控件,怎么才显示那么小的视频?哈哈,问题来了,小视频怎么动态适配控件大小?

  • 小视频适配大控件(动态调整视频显示的大小)

不说原理了,我也是百度的,普通的LayoutParams只能调整控件的大小,当视频比控件小时,视频只能显示大默认大小,可是怎么来调整呢?请看代码↓

自定义VideoView控件CustomVideoView.java

/*** @author  Created by MrRight on 2017/10/24.*/
public class CustomVideoView extends VideoView{private Context mContext;final int defaultHeight=200; //单位DPpublic CustomVideoView(Context context) {super(context);mContext=context;}public CustomVideoView(Context context, AttributeSet attrs) {super(context, attrs);mContext=context;}public CustomVideoView(Context context, AttributeSet attrs, int defStyleAttr) {super(context, attrs, defStyleAttr);mContext=context;}//widthMeasureSpec 和 heightMeasureSpec的值 由父容器决定@Overrideprotected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {super .onMeasure(widthMeasureSpec,heightMeasureSpec);// 默认高度,为了自动获取到focusint width = MeasureSpec.getSize(widthMeasureSpec);int height = width;// 这个之前是默认的拉伸图像if (this.width > 0 && this.height > 0) {width = this.width;height = this.height;}setMeasuredDimension(width, height);}private int width,height;public void setMeasure(int width, int height) {this.width = width;this.height = height;}
}

怎么用呢!!很简单,继续看代码↓

videoViewParent.post(new Runnable() {@Overridepublic void run() {int[] widthAndHeight=getWidthAndHeight(holder.videoViewParent,dynamicsBean.getWeight(),dynamicsBean.getHeight());videoView.getHolder().setFixedSize(widthAndHeight[0], widthAndHeight[1]);// 重绘VideoView大小,这个方法是在重写VideoView时对外抛出方法videoView.setMeasure(widthAndHeight[0], widthAndHeight[1]);// 请求调整videoView.requestLayout();}
});

就这样,视频可以按你的需求行进动态调整了!!

  • VideoView的常用监听和作用

VideoView有好多监听,真的是好多,许多监听是重复的,至于怎么重复的?为什么重复?有兴趣的自己去看看!首先看第一个非常重要的一个监听:点击事件和双击事件的监听,你们有没有试过设置OnClick事件?是不是没有什么用啊?没用就对了,点击事件的正确姿势是↓↓↓

/** 对VideoView setOnClickListener时,发现无效,搜索一番后找到解决方案;* 同时监听VideoView的点击双击和滑动事件,通过对VideoView的OnTouchListener设置进行监听,* 首先实例化一个手势识别器,并返回它的onTouchEvent。* 然后初始化GestureDetector ,这里面有一个坑,如果单纯的设置OnGestureListener,发现当onDown的返回值为true的* 时候可以响应单击长摁和滑动事件,为false的时候只会响应长摁事件;如果想要监听双击事件,就要对GestureDetector设* 置OnDoubleTapListener,需要注意的的是,在OnGestureListener的onDown返回值为false的时候OnDoubleTapListener* 里面所有的回调是不会去响应的*/
holder.videoView.setOnTouchListener(new View.OnTouchListener() {GestureDetector mGesture;@Overridepublic boolean onTouch(View v, MotionEvent event) {if (mGesture == null) {mGesture = new GestureDetector(context, new GestureDetector.SimpleOnGestureListener() {@Overridepublic boolean onDown(MotionEvent e) {//返回false的话只能响应长摁事件return true;}@Overridepublic void onLongPress(MotionEvent e) {super.onLongPress(e);}@Overridepublic boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX, float distanceY) {return super.onScroll(e1, e2, distanceX, distanceY);}});mGesture.setOnDoubleTapListener(new GestureDetector.OnDoubleTapListener() {@Overridepublic boolean onSingleTapConfirmed(MotionEvent e) {controlLayoutShowAndHiden(holder.controlLayout,holder.cancheImage);return true;}@Overridepublic boolean onDoubleTap(MotionEvent e) {return true;}@Overridepublic boolean onDoubleTapEvent(MotionEvent e) {return false;}});}return mGesture.onTouchEvent(event);}
});

OK!点击事件看完之后,我们看下剩下的其他的监听方法,剩下的比较简单,光看名字就知道是干什么用的,我们只写下方法和作用,不再赘述

videoView.setOnErrorListener(new MediaPlayer.OnErrorListener() {@Overridepublic boolean onError(MediaPlayer mp, int what, int extra) {if(what==MediaPlayer.MEDIA_ERROR_UNKNOWN //未指定的媒体播放器错误。||what==MediaPlayer.MEDIA_ERROR_SERVER_DIED //媒体服务器死了。在这种情况下,应用程序必须释放||what==MediaPlayer.MEDIA_ERROR_NOT_VALID_FOR_PROGRESSIVE_PLAYBACK//视频流,其容器对逐行扫描无效。||what==MediaPlayer.MEDIA_ERROR_MALFORMED//文件或网络操作错误||what==MediaPlayer.MEDIA_ERROR_UNSUPPORTED//比特流符合相关的编码标准或文件规范,但 媒体框架不支持该功能。||what==MediaPlayer.MEDIA_ERROR_TIMED_OUT//超时||what==MediaPlayer.MEDIA_ERROR_IO){ //IO刘错误if(controlImageBig.getVisibility()==View.VISIBLE){controlImageBig.setBackgroundResource(R.drawable.vodeo_retry);}}return true;//如果设置true就可以防止他弹出错误的提示框!}
});videoView.setOnInfoListener(new MediaPlayer.OnInfoListener() {@Overridepublic boolean onInfo(MediaPlayer mp, int what, int extra) {if (what==MediaPlayer.MEDIA_INFO_VIDEO_RENDERING_START){controlImageBig.setVisibility(View.GONE);cancheImage.setVisibility(View.GONE);controlImageBig.setBackgroundResource(R.drawable.eventdynamics_play_big);}LogUtils.i(TAG,"\n extra is "+extra+"\n what is "+what);return false;}
});videoView.setOnPreparedListener(new MediaPlayer.OnPreparedListener() {@Overridepublic void onPrepared(MediaPlayer mp) {Log.d(TAG,"onPrepared methmod is called and position is "+position);int duration=holder.videoView.getDuration();totleTime.setText(intTimeToString(duration));seekBar.setMax(duration);videoViewParent.setOnClickListener(new View.OnClickListener() {@Overridepublic void onClick(View v) {controlLayoutShowAndHiden(holder.controlLayout,holder.cancheImage);}});}
});videoView.setOnCompletionListener(new MediaPlayer.OnCompletionListener() {@Overridepublic void onCompletion(MediaPlayer mp) {threadPoolUtils.shutDownNow();if(cancheImage.getVisibility()==View.GONE){cancheImage.setVisibility(View.VISIBLE);}if(controlImageBig.getVisibility()==View.GONE){controlImageBig.setVisibility(View.VISIBLE);}playControl.setImageResource(R.drawable.eventdynamics_play);seekBar.setProgress(0);}
});

好了,大概就这么多,后续有新东西还会持续更新,大家有什么好的建议也可以留言交流

Android VideoView播放网络视频简介相关推荐

  1. Android VideoView播放网络视频简介(转)

    最近项目中用到了很多视频播放的地方,不管是聊天发送的视频消息,还是类似内涵段子的视频列表,都会涉及这些知识,不过网上的知识都很零散,一会找缓存方法,一会找预览图片的方法,一会找视频动态修改尺寸的方法, ...

  2. Android VideoView播放网络视频

    VideoView的布局: <VideoView android:id="@+id/videoView" android:layout_width="match_p ...

  3. Android使用VideoView播放网络视频

    Android支持播放网络上的视频.在播放网络上的视频时,牵涉到视频流的传输,往往有两种协议,一种是HTTP,一种是RTSP.这 两种协议最大的不同是,HTTP协议,不支持实时流媒体的播放,而RTSP ...

  4. Android 实现播放网络视频 内容附源码下载链接

    <?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android=&quo ...

  5. 超简单VideoView播放网络视频和本地视频

    控件 <VideoViewandroid:id="@+id/video_details"android:layout_width="match_parent&quo ...

  6. Android之MediaPlayer播放网络视频的实现方法

    前段时间忙于工作,现在有时间来分享一下: 这篇文章主要介绍了Android的MediaPlayer播放网络视频的实现方法,是一个非常实用的功能,需要的朋友可以参考下 前面讲解了MediaPlayer播 ...

  7. Android提高第二十一篇之MediaPlayer播放网络视频

    本文来自http://blog.csdn.net/hellogv/ ,引用必须注明出处! 上次讲解了MediaPlayer播放网络音频,介绍了MediaPlayer关于网络音频的缓冲和进度条控制的方法 ...

  8. android videoview 播放之前短暂黑屏

    最近在做视频闪屏页,但是遇到了一个困难 VideoView播放视频的时候会出现黑屏,能够清晰看到黑色的屏幕,很不美观 照惯例,遇到问题先看有没有网友解决过,发现了几篇博客 Android VideoV ...

  9. Android VideoView无法播放网络视频

    今天学习Android播放视频和音频,其中在练习播放视频的时候无法播放网络视频,网络视频是别人发布在网上的,但是把视频放在本地是可以的,最后推测是没有开放网络的访问权限的问题,果然开放了之后就能正常访 ...

最新文章

  1. mysql表导出和导入命令行_MySQL命令行导出导入数据库和数据表-Go语言中文社区...
  2. Linux容器的发展历史及其未来趋势
  3. android编译.a文件,Android 7.1源码编译导入AS完整教程
  4. 运行scrapy shell 'http://quotes.toscrape.com'出现错误ValueError: invalid hostname: 'http
  5. 彻底删除 XP 自带的 Windows Messenger方法
  6. 算法--二分查找--求平方根(循环法/递归法)
  7. api网关 android,如何通过Android上的retrofit2使用Cognito Credentials调用API网关?
  8. LeetCode刷题(5)
  9. 现代ups电源及电路图集_不间断电源维修,服务靠谱
  10. 聚类 | Map-Equation多级网络聚类模型——InfoMap
  11. 后台查询到前台所需,数据结构转换的通用方法(三) 地图-色斑图的对接
  12. Android对接蓝牙打印机
  13. c语言头结点存放元素,【笔记】带头节点的单链表的C语言实现
  14. Leetcode(934)——最短的桥
  15. zoj 1104 Leaps Tall Buildings(超人不会飞- -。。)
  16. 【示波器】基于FPGA的数字示波器设计实现
  17. 双软企业认定的好处有哪些
  18. linux网卡驱动更新方法
  19. <转>OSPF OE2和OE1外部路由详解(主要解释了下OE2为什么没默认负载均衡)
  20. linux sendmail

热门文章

  1. 这个夏天:应用试客已将积分墙逼到墙角,ASO路上的那些掮客
  2. Linux for pogoplug pro 安装指导手册
  3. Http协议那些事儿
  4. 【小沐学NLP】Python实现聊天机器人(Selenium、七嘴八舌)
  5. pygame战棋游戏制作之战棋棋子设置(二)
  6. kali虚拟机网络配置
  7. Flutter - 仿微信右上角pop弹框封装 - JhPopMenus
  8. 抓取主板市盈率,市净率和股息率
  9. 第 5 届 FEDAY 前端大会的完整 PPT 内容已出炉-站在大牛的肩膀上学习
  10. super关键字用法