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()方法中去执行

更多相关文章

  1. Android手势源码浅析----手势识别
  2. View那些事儿(1) -- View绘制的整体流程
  3. Android(安卓)View体系(二)实现View滑动的六种方法
  4. android音乐播放器-------使用android系统自带的数据库
  5. 解决ios 同层播放video 类似QQ登入背景图是视频(vue)
  6. 开发android应该注意的
  7. android中YUV转RGB的方法
  8. 浅谈Android应用的退出
  9. java.lang.NullPointerException空指针问题

随机推荐

  1. Android(安卓)Service生命周期及用法
  2. android动态加载已安装apk中的方法
  3. TextView: android中TextView实现单行跑马
  4. android之Layout(一)
  5. Android(安卓)启动页面优化 (白屏 、等待
  6. Android中GridView使用
  7. Android上鲜为人知的UI控件介绍和使用
  8. Android(安卓)Studio初学习体会
  9. android语音识别技术
  10. Android开发技巧:动态创建UI界面