最近在做一期有关于视频的项目开发。因为项目周期比较紧,而且自己以前也没有对于视频相关的经验积累。所以在开发的时候遇到了问题,自己尝试解决并记录下来。(PS:视频都是下载完再进行播放类似于微信朋友圈的视频功能,播放组件用的是分装的原生的VideoView)
一、视频播放时会有短暂的黑屏时间:
- 产生原因:视频文件加载到内存中是需要时间,这个时间可能导入VideoView全黑。
- 解决方法(1):给VideoView添加
MediaPlayer.OnPreparedListener
监听事件,在其onPrepared(MediaPlayer mp)
方法回调中播放视频这个时候视频已经完成了加载。(PS:此方法在有些情况下使用有些问题,因为播放视频的时候MediaPlayer.OnPreparedListener
监听不到回调,具体为什么自己也没有做相关的调研,如果有谁知道希望能分享一下)。 - 解决方法(2):笨方法,同时也是最管用的方法。在VideoView执行
start()
方法时视频的预览图不是立即消失而是延迟几百毫秒之后消失,这是视频已经加载完成,当然体验上有些不好。
二、在进入有VideoView界面的Activity时会出现闪黑屏的情况(如论视频是否播放):
产生原因:不祥(自己没有找到认为正确的答案)
解决方法:在整个界面创建之前添加这行代码
getWindow().setFormat(PixelFormat.TRANSLUCENT);
三、当前界面有视频播放时进入其他界面,然后跳转回来后VideoView展示全黑(按home键再次进入app也会有同样的问题):
产生原因:VideoView被回收掉,而自己没做VideoView的状态保存处理
解决方法:在VideoView所在的Activity或者Fragment的生命周期中处理VideoView视频播放和暂停。
四、在类似微信列表页视频播放点击大图播放时列表的VideoView回出现在大图的VideoView之上(PS:如果列表的VideoView和大图播放的VideoView不是同一个):
- 产生原因:SurfaceView默认会出现在最顶部的。
- 解决方法: 小图播放时要隐藏掉(GONE而不是INVISIBLE)。
五、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)
方法。然后再在方法里处理下一个视频的播放以及上一个的停止。
六、使用VideoView造成界面其他组价焦点产生“遗失”:
现象:在ViewTreeObserver.addOnPreDrawListener添加新的OnPreDrawListener的onPreDraw多次执行。
解决办法(1):使用SurfaceView+MediaPlayer自定义播放器
解决办法(2):对VideoView的构造函数中的焦点处理的方法进行反处理,即在VideoView子类(这里应该就是自己写的自定义VideoView其继承与VideoView)的构造方法中进行反处理。
//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<Pair<InputStream, MediaFormat>>();
mCurrentState = STATE_IDLE;
mTargetState = STATE_IDLE;
}
/*其他代码省略*/
}
七、在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()
方法进行延迟播放。一般这个时间不会太长,几百毫秒就可以。视觉感官上也还好。
以上是自己在仅仅两周开发使用VideoView开发视频有关项目中遇到的问题,和一些不是很成熟的解决方案。