Android 不得不说的VideoView的一些坑及其解决方案

最近公司做动态展示新添加了视频,然后去摸索了一些视频的相关问题,最终选择了Android原生的VideoView。开发中遇到了一些坑给大家分享出来,不得不说很坑,希望给大家做视频播放做一个参考:先总结如下:

VideoView的问题及其解决方案:

1.视频播放时会有短暂的黑屏时间: 
产生原因:视频文件加载到内存中是需要时间,这个时间可能导入VideoView全黑。

解决方法(1):给VideoView添加MediaPlayer.OnPreparedListener 监听事件,在其onPrepared(MediaPlayer mp) 方法回调中播放视频这个时候视频已经完成了加载。(PS:此方法在有些情况下使用有些问题,因为播放视频的时候MediaPlayer.OnPreparedListener 监听不到回调,要先用此方法解决最本质问题得好好研究一下源码)。 
解决方法(2):笨方法,同时也是最直接的方法。在VideoView执行start() 方法时视频的预览图不是立即消失而是延迟几百毫秒之后消失,这是视频已经加载完成,当然体验上有些不好。

                        new Thread(new Runnable() {                                @Override                                public void run() {                                    SystemClock.sleep(200);                                    runOnUiThread(new Runnable() {                                        @Override                                        public void run() {                                            //执行让预览图消失的方法                                        }                                    });                                }                            }).start();

2.进入有VideoView界面的Activity时会出现闪黑屏的情况(如论视频是否播放):

产生原因:不祥(本人认为好像是窗口的问题)

解决方法:在整个界面创建之前添加这行代码getWindow().setFormat(PixelFormat.TRANSLUCENT); 
(PixelFormat.TRANSPARENT和PixelFormat.TRANSLUCENT作用差不多,都是使窗口支持透明度)

3.当前界面有视频播放时进入其他界面(或者谈起PopupWindow/分享到微信、朋朋友圈、QQ等),然后跳转回来后VideoView展示全黑(按home键再次进入app也会有同样的问题):

产生原因:VideoView被回收掉,而自己没做VideoView的状态保存处理

解决方法:在VideoView所在的Activity或者Fragment的生命周期中处理VideoView视频播放和暂停。(查看VideoView的生命周期)

4.在类似微信列表页视频播放点击大图播放时列表的VideoView回出现在大图的VideoView之上(PS:如果列表的VideoView和大图播放的VideoView不是同一个): 
产生原因:SurfaceView默认会出现在最顶部的。 
解决方法: 小图播放时要隐藏掉(GONE而不是INVISIBLE)。

5.VideoView嵌套ViewPager使用时,在滑动ViewPager过程中视VideoView会出现透明(此时VideoView是自动播放)(PS:此时Activity的主题为android:theme=”@style/Transparent”)。

产生原因:ViewPager在执行public void onPageSelected(int position) 方法时当前界面还是展示两个View。即下一个View并没有完全漏出来。

解决方法:定义ViewPager的ViewPager.OnPageChangeListener接口,覆盖public void onPageScrolled(int postion, float v, int i)方法,监听让下一个界面完全展现出来之后在执行public void onPageSelected(int position)方法。然后再在方法里处理下一个视频的播放以及上一个的停止。

6.使用VideoView造成界面其他组价焦点产生“遗失”:

现象:在ViewTreeObserver.addOnPreDrawListener添加新的OnPreDrawListener的onPreDraw多次执行。

解决办法(1):使用SurfaceView+MediaPlayer自定义播放器

解决办法(2):对VideoView的构造函数中的焦点处理的方法进行反处理,即在VideoView子类(这里应该就是自己写的自定义VideoView其继承SurfaceView)的构造方法中进行反处理。

自定义的VideoView public class VideoView extends SurfaceView        implements MediaPlayerControl, SubtitleController.Anchor {    private String TAG = "VideoView";    /*其他代码省略*/    //每个构造函数中都执行initVideoView    public VideoView(Context context) {        super(context);        initVideoView();    }    public VideoView(Context context, AttributeSet attrs) {        this(context, attrs, 0);        initVideoView();    }    public VideoView(Context context, AttributeSet attrs, int defStyleAttr) {        this(context, attrs, defStyleAttr, 0);    }    public VideoView(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {        super(context, attrs, defStyleAttr, defStyleRes);        initVideoView();    }    /*其他代码省略*/    private void initVideoView() {        mVideoWidth = 0;        mVideoHeight = 0;        getHolder().addCallback(mSHCallback);        getHolder().setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);        //start     下边3行代码是对焦点进行的处理,以及自己所谓的反处理        setFocusable(true);  //子类setFocusable(false);        setFocusableInTouchMode(true);   //子类setFocusableInTouchMode(false);        requestFocus();   //子类clearFocus();        //end        mPendingSubtitleTracks = new Vector>();        mCurrentState = STATE_IDLE;        mTargetState  = STATE_IDLE;    }    /*其他代码省略*/ }

7.在VideoView的MediaPlayer.OnCompletionListener 回调监听public void onCompletion(MediaPlayer mp) 方法里进行视频的播放(PS:这个指的是视频的循环播放),在有些手机上不能正常重新播放。

产生原因:在部分手机上VideoView的MediaPlayer.OnCompletionListener 回调监听public void onCompletion(MediaPlayer mp) 方法里此时`VideoView.isPlaying() 的值还是为true。

解决办法:在VideoView的 MediaPlayer.OnCompletionListener 回调监听 public void onCompletion(MediaPlayer mp) 方法里对`VideoView.start() 方法进行延迟播放。一般这个时间不会太长,几百毫秒就可以。视觉感观上也还好。

8.手机分辨率导致的无法播放此视频的问题

产生原因:视频的分辨率与手机分辨率的问题

解决办法:设置surfaceView的布局参数

   //首先取得video的宽和高                    int vWidth = player.getVideoWidth();                    int vHeight = player.getVideoHeight();                    if (vWidth > video_view.getWidth() || vHeight > video_view.getHeight()) {                        //如果video的宽或者高超出了当前屏幕的大小,则要进行缩放                        float wRatio = (float) vWidth / (float) video_view.getWidth();                        float hRatio = (float) vHeight / (float) video_view.getHeight();                        //选择大的一个进行缩放                        float ratio = Math.max(wRatio, hRatio);                        vWidth = (int) Math.ceil((float) vWidth / ratio);                        vHeight = (int) Math.ceil((float) vHeight / ratio);                        //设置surfaceView的布局参数                        video_view.setLayoutParams(new LinearLayout.LayoutParams(vWidth, vHeight));                        //然后开始播放视频                        player.start();                    }

这个写在setOnPreparedListener的onPrepared()方法中去执行。

转自:https://blog.csdn.net/madreain/article/details/52143787

更多相关文章

  1. Android(安卓)View从源码的角度分析事件的注册和接收
  2. android -- sim/usim卡导联系人
  3. Android定时任务的应用及实现
  4. 2016年腾讯android开发工程师面试题目
  5. 在 Android(安卓)中使用 JNI 的总结
  6. android 音视频相关知识
  7. android绘制播放音频的波形图
  8. Android进阶——借助Loader机制以一种更优美的方式异步加载数据(
  9. Android的签名文件生成两种方法

随机推荐

  1. 常用标签,属性,表格
  2. 安装编辑器与常用插件
  3. html预习,请老师审批,
  4. 实例演示flex容器与项目中常用的属性
  5. 三行三列的定位布局中演示QQ客服的固定定
  6. 对于模板字面量与标签函数、解构赋值于对
  7. js中常用的字符串函数、数组函数、分支与
  8. 表单,框架,选择器,css的三种插入样式(内联,外
  9. 字体样式调用、布局原则、盒模型等
  10. 0701学习实战作业