推荐一个视频播放器封装库的演示项目:iMusic视频播放器
- 若你对音乐播放器有需求请移步至Android音频播放器封装
之前开发公司项目时,在部分项目中有用到著名的开源项目:节操视频播放器(后更名为饺子播放器)。然而在后期的项目维护时,索性从头开始,独立封装视频播放器框架,封装基础功能,方便后期迭代和维护。现已将其整理开源iMusic。
此播放器支持的特性包括但不限于:体积小、极简集成、完全自定义交互UI、支持常规的横竖屏切换、可拖拽的小窗口切换、可拖拽的全局悬浮窗口播放、界面跳转无缝衔接播放、全屏播放下手势识别调节等功能。网络数据交互采用MVP思想搭建框架。
我们先来看下iMusic项目效果图:
视频播放器框架结构一览:
播放器框架图示
图中的TrackListener为播放器本身。如图所示,播放器框架设计之初被封装设计成为了一个可自定义UI、单例、代理模式的交互播放器。本篇将分三大类叙述视频播放器的封装实现过程。
一、解码渲染
解码器这里选择基于系统的MediaPlayer实现,如果你想更换解码器,请下载源码自定更换。画面渲染使用TextrueView实现,至于为什么不使用SurfaceView,自行Google一波。
1.TextureView创建和初始化
//初始化一个TextureView并添加至ViewGroup或找到你的TextureView 组件
mTextureView=new TextureView(getContext());
//设置画布监听
textureView.setSurfaceTextureListener(this);
//添加至布局
fragment.addView(textureView,new LayoutParams(LayoutParams.MATCH_PARENT,LayoutParams.MATCH_PARENT, Gravity.CENTER));
/**
* TextureView准备好了回调
* @param surface 内部画布渲染surface
* @param width TextureView布局宽
* @param height TextureView布局高
*/
@Override
public void onSurfaceTextureAvailable(SurfaceTexture surface, int width, int height) {
Logger.d(TAG,"onSurfaceTextureAvailable-->width:"+width+",height:"+height);
//这里对画面改变、转场播放做了处理,声明一个mSurfaceTexture ,在TextureView发生变化时更新
if (mSurfaceTexture == null) {
mSurfaceTexture = surface;
//prepare();
} else {
mTextureView.setSurfaceTexture(mSurfaceTexture);
}
}
/**
* TextureView宽高发生变化时回调
* @param surface 内部surface
* @param width 新的TextureView布局宽
* @param height 新的TextureView布局高
*/
@Override
public void onSurfaceTextureSizeChanged(SurfaceTexture surface, int width, int height) {
Logger.d(TAG,"onSurfaceTextureSizeChanged-->width:"+width+",height:"+height);
}
/**
* TextureView销毁时回调
* @param surface 内部surface
* @return Most applications should return true.
*/
@Override
public boolean onSurfaceTextureDestroyed(SurfaceTexture surface) {
Logger.d(TAG,"onSurfaceTextureDestroyed");
return null==mSurfaceTexture;
}
/**
* TextureView刷新时回调
* @param surface 内部surface
*/
@Override
public void onSurfaceTextureUpdated(SurfaceTexture surface) {
}
2.MediaPlayer初始化和准备播放
mMediaPlayer = new MediaPlayer();
mMediaPlayer.setAudioStreamType(AudioManager.STREAM_MUSIC);
//设置准备播放监听器,在onPrepared回调中开始播放
mMediaPlayer.setOnPreparedListener(this);
//...此处省去一系列监听设置
//异步准备
mMediaPlayer.prepareAsync();
/**
* 播放器准备好了
* @param mp 解码器
*/
@Override
public void onPrepared(MediaPlayer mp) {
Logger.d(TAG,"onPrepared");
if(null!=mSurfaceTexture){
if(null!=mSurface){
mSurface.release();
mSurface=null;
}
mSurface =new Surface(mSurfaceTexture);
mp.setSurface(mSurface);
}
//开始播放
mp.start();
}
二、单例
要实现单例播放,就必须有个被设计为单例模式的第三方委托代理类持有MediaPlayer,此库就取名为 VideoPlayerManager,VideoPlayerManager持有MediaPlayer和TextureView。播放视频前需要先释放一波,然后更新监听器。
/**
* 开始播放的入口开始播放、准备入口
*/-
public void startPlayVideo(){
//还原可能正在进行的播放任务
VideoPlayerManager.getInstance().onReset();
//更新内部监听器
VideoPlayerManager.getInstance().addOnPlayerEventListener(this);
//这个用在列表销毁时判断播放器是否需要销毁
setWorking(true);
//准备画面渲染图层
if(null!=mSurfaceView){
addTextrueViewToView(BaseVideoPlayer.this);
//开始准备播放
VideoPlayerManager.getInstance().startVideoPlayer(mDataSource,getContext());
}
}
//VideoPlayerManager.getInstance().onReset();
/**
* 放播放器
*/
private void reset() {
try {
if(null!=mMediaPlayer){
if(mMediaPlayer.isPlaying()){
mMediaPlayer.stop();
}
mMediaPlayer.reset();
mMediaPlayer.release();
mMediaPlayer=null;
}
}catch (RuntimeException e){
e.printStackTrace();
}
}
三、自定义交互UI
播放器提供了三个交互类型的基类,分别是BaseVideoController(播放控制器)、BaseCoverController(封面控制器)、BaseGestureController(手势识别控制器),要实现自定义UI交互,需继承此三个类实现自己的业务交互。播放事件的UI刷新机制,是由BaseVideoPlayer统一调度,
1. 自定义交互控制器
交互控制器在本项目中被定义为:用户与播放器的UI交互控制器。如需自定义请继承BaseVideoController类并实现其抽象方法,调用播放器通道的setVideoController(V controller);绑定控制器。</br>
如在播放过程中开启小窗口、悬浮窗播放器时,可指定控制器小窗口、悬浮窗专用的交互控制器。悬浮窗口的关闭按钮不支持自定义。另外,控制器还提供了子线程中的播放进度方法,100毫秒执行一次,主线程的播放进度方法是1000毫秒执行一次,请注意你的UI刷新。
2. 自定义封面控制器
封面控制器是指视频在开始播放前的封面显示图层,如需自定义请继承BaseCoverController类,调用播放器通道的setVideoCoverController(C controller);绑定控制器。BaseCoverController中默认实现了点击开始播放能力。若需自定义点击自己的View开始播放,请实现点击事件后
调用BaseCoverController的mOnStartListener.onStartPlay();方法开始播放。
3. 自定义手势识别器
手势识别器是播放器在全屏状态下播放时,播放器内部检测用户手势滑动行为对播放器功能做出改变时的UI交互提示,如快进、快退、音量、亮度等调节后的UI显示交互,如需自定义
请继承BaseGestureController类,实现其抽象方法,调用调用播放器通道的setVideoGestureController(G controller);绑定控制器。自定义手势识别器还支持消费手势触摸事件,详见BaseGestureController抽象方法onTouchEnevt介绍。
全部功能请阅读视频播放器Wiki
网友评论