这两天心血来潮,想做一个安卓版的视频播放器,网上说用安卓自带的videoView就可以实现,自己试了下,发现真是弱爆了,于是使用vitamio开源的框架自己写了一个。
vitamio简略介绍
可以播放 720p甚至1080p的视频,
支持的视频格式:mkv,flv,np4,mov,ts,rmvb
好了,vitamio就介绍这么多,进入主题
异步任务与主界面
在主界面需要获取SD卡下所有能播放的视频名,在主线程去遍历SD卡不太好,这里推荐使用异步任务去遍历。
这里异步任务遍历有一个很大的好处,就是在doInBackground中遍历SD下所有文件,发现视频文件可以通过发布进度(onProgressUpdate)方式去显示视频文件(发现一个就在activity的列表里显示一个,而不是遍历完了一起显示)。
在异步任务重,通过接口回调的方式更新界面列表,接口如下
/**
* 异步遍历SD卡回调接口
* @author yu
*
*/
public interface onVideoFileFindListener{
/**
* 找到视频文件的回调方法
* @param videoFile
*/
public void onVideoFileFind(File videoFile);
/**
* 异步搜索结束的回调方法
*/
public void onFindDone();
}
先通过构造方法传入接口的实现类
private onVideoFileFindListener listener;
public VideoFileAsyncTask(onVideoFileFindListener listener) {
super();
this.listener = listener;
}
在doInBackground中遍历sd卡,相关代码如下
@Override
protected Object doInBackground(String... params) {
File root=Environment.getExternalStorageDirectory();
searchVideoFile(root);
return null;
}
/**
* 搜索指定目录下可以播放的视频文件
* @param file
*/
private void searchVideoFile(File file){
if(file==null){//文件为空直接返回
return;
}
if(file.isDirectory()){//如果是文件夹
File[] files = file.listFiles();
for(File f:files){//遍历该文件夹下的全部 在递归
searchVideoFile(f);
}
}else if(file.isFile()){//如果是文件 判断是否是能播放的视频文件
String fileName=file.getName();
if(fileName.endsWith(VIDEOTYPE_FLV)||fileName.endsWith(VIDEOTYPE_MKV)||fileName.endsWith(VIDEOTYPE_MP4)||fileName.endsWith(VIDEOTYPE_RMVB)||fileName.endsWith(VIDEOTYPE_TS)){
//如果是能播放的视频文件 使用接口回调 注意这里是工作线程 不能操作UI 要通过发布进度的方式更新UI
publishProgress(file);
}
}
}
找到可以播放的视频文件通过发布进度,使用接口回调更新界面列表
(在工作线程更新UI会出问题的)
@Override
protected void onProgressUpdate(File... values) {
//这里是主线程 在这里更新UI
File file=values[0];
listener.onVideoFileFind(file);
}
异步任务工作完了需要通知界面,代码如下
protected void onPostExecute(Object result) {
listener.onFindDone();
}
主界面activity要实现onVideoFileFindListener接口,并重新接口的抽象方法,主要代码如下
public void onVideoFileFind(File videoFile) {
if(videoFile==null){
return;
}
//通过视频文件获取缩略图
MediaMetadataRetriever retriever=new MediaMetadataRetriever();
retriever.setDataSource(videoFile.getAbsolutePath());
Bitmap bitmap=retriever.getFrameAtTime();
VideoEntity entity=new VideoEntity(videoFile.getName(), videoFile.getAbsolutePath(), bitmap);
list.add(entity);
adapter.notifyDataSetChanged();
}
@Override
public void onFindDone() {
listView.removeHeaderView(headerView);
isSearch=false;
}
通过MediaMetadataRetriever获取视频文件缩略图,找到一个视频文件就加入到集合中并更新adapter,异步任务完成后移除listview顶部的headerview(用来显示正在搜索)
视频播放activity
使用vitamio的videoview来播放SD卡的视频文件,需要下载vitamio的框架
vitamio 在github上的地址:https://github.com/yixia/VitamioBundle
使用vitamio的videoview需要在清单文件中声明vitamio的activity,
<!-- 声明维他命的activity -->
<activity
android:name="io.vov.vitamio.activity.InitActivity"
android:configChanges="orientation|screenSize|smallestScreenSize|keyboard|keyboardHidden|navigation"
android:launchMode="singleTop"
android:theme="@android:style/Theme.NoTitleBar"
android:windowSoftInputMode="stateAlwaysHidden" />
在activity的onCreate中初始化
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
if(!LibsChecker.checkVitamioLibs(this)){//初始化 vitamio
return;
}
setContentView(R.layout.activity_main);
。。。。。。
vitamio 的videoView使用和安卓自带的videoview很相似,这里说几个重要的方法
setVideoPath(videoPath)设置视频文件所在的路径。
videoView.setOnPreparedListener设置视频加载完成监听事件,视频加载完成后可以获得视频文件相关信息。
videoView.setVideoLayout(type, 0);设置视频大小,
videoView.seekTo跳转到指定位置播放
视频控制
vitamio自带有视频控制MediaController,这个自带的不好用,你们都懂,没办法只能自己写一个,效果如图
原理是放一个布局在videoView上面,点击屏幕的时候控制界面出现,在点一下就消失,更多设置 使用popupwindow显示。
这里有几点需要注意的地方,
1,获取视频时长需要在videoView.setOnPreparedListener回调的时候处理;
2,屏幕亮度如果没有设置,获取的默认值是-1(亮度区间0-1);