之前在自己的一个项目中用到过视频播放,今天抽空把遇到的坑都写下来,顺便给将要用到的朋友提个醒。
首先说下开源的视频播放框架有好几个,我这里主要讲我用到的这个,那就是Vitamio。有关vitamio的详细介绍,有一位朋友写了比较详细的介绍,也是开发者之一,有时间的朋友可以移步这里。
一.项目导入:
我是用Android Studio开发的,将vitamio以一个module导入,再它作为一个依赖注入到需要使用的项目。eclipse的话同样将vitamio工程导入再设置成一个library即可。
Vitamio下载。下载后只导入vitamio包下的代码即可,sample当然也可以看看。as导入后可能会有报错的现象,这是因为sdk版本不一致的原因造成的,只需把Vitamio项目中build.gradle文件里的以下字段修改下
android {
compileSdkVersion 24 //修改版本和原项目保持一致
buildToolsVersion "24.0.2" //修改版本和原项目保持一致
defaultConfig {
minSdkVersion 14 //修改版本和原项目保持一致
targetSdkVersion 24 //修改版本和原项目保持一致
}
二.使用
在Manifest文件中声明Vitamio需要使用的初始化Activity,播放网络视频的话还有联网权限,我这次测试用的就是播放联网视频。
在activity的onCreate方法前添加如下代码检测是否成功导入相关资源如.so文件
public void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
if (!io.vov.vitamio.LibsChecker.checkVitamioLibs(this))
return;
setContentView...//你的代码
}
布局文件声明,外层用一个FrameLayout包裹背景设置为黑色(全屏时若背景不是黑色视频又不能完全贴合屏幕会留白很难看)。
好啦,现在来测试运行下
现在有个问题,controller的布局怎么在页面最底部,想象中应该是在VideoView的底部,还有个小bug是 会往上跳(如VideoView上面有个button的话这时就只有一半可见了,暂时没发现因为什么原因)。只有看看源码了,后发现源码中Controller是以PopupWindow的方式添加到屏幕上的。贴上其中关键一小段代码
if (mFromXml) {
setVisibility(View.VISIBLE);
} else {
int[] location = new int[2];
mAnchor.getLocationOnScreen(location);
Rect anchorRect = new Rect(location[0], location[1], location[0] + mAnchor.getWidth(), location[1] + mAnchor.getHeight());
mWindow.setAnimationStyle(mAnimStyle);
setWindowLayoutType();
mWindow.showAtLocation(mAnchor, Gravity.NO_GRAVITY, anchorRect.left, anchorRect.bottom);
}
mAnchor是VideoView的父View(若宽高是match_parent),而这里location又是使用的mAnchor的left和bottom作为PopupWindow的显示位置,所以自然都是在最下方了。这是mFromXml为false的情况(使用一个参数的Controller构造方法都会走到这),如果为true的话可以看到直接设置显示就OK了,那我们能不能直接让它走true的情况呢,其实true就代表把Controller添加到一个父View中,由于代码过多就不一一贴上来了,直接出个解决方案吧。简单起见我们给MediaController增加一个构造方法,把父容器传进来然后将controller添加到其中,把mFromXml赋值为true,给Controller添加布局参数。代码如下:
public MediaController(Activity activity, boolean fromXml, View container) {
super(activity);
//此处初始化了AudioManager和Context
initController(activity);
//此处的activity是为后面获取当前屏幕方向而准备。接受Context类型再强制转换为activity也行。
mActivity = activity;
//设置mFromXml为true
mFromXml = fromXml;
//初始化Controller布局文件
mRoot = makeControllerView();
if(container instanceof FrameLayout){
FrameLayout.LayoutParams p = new FrameLayout.LayoutParams(LayoutParams.MATCH_PARENT,
LayoutParams.WRAP_CONTENT);
//在父View底部
p.gravity = Gravity.BOTTOM;
mRoot.setLayoutParams(p);
((FrameLayout)container).addView(mRoot);
}
}
好再来看下效果
差不多就这样吧,到现在要实现大小屏切换了,先需要优化下布局,增加大小屏切换按钮、缩略图、点击开始图片按钮,我觉得controller太高了而且带文件名不好看(有更改文件名的方法,默认显示URL截取最后一个 / 之后的内容),我就不贴布局文件了直接看效果吧。
三.大小屏流畅切换
至于全屏的话我的方法就是将要隐藏的View添加到一个集合中,再根据需要遍历隐藏和显示。我是强制设置了竖屏,只能通过点击图片按钮切换。记得在当前activity声明这些属性
android:screenOrientation="portrait"
android:configChanges="orientation|keyboardHidden|screenLayout|screenSize"
然后重写activity的onConfigurationChanged方法,当屏幕发生变化的时候通过回调判断当前是横向还是纵向,再进行放大缩小。还有就是隐藏系统通知栏等
//这两个方法
getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,
WindowManager.LayoutParams.FLAG_FULLSCREEN);
getWindow().clearFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN);
到现在基本完成全屏播放了,录屏效果不好做不了gi图,而且上传大小又有限制就用图片代替了,可以看到上面这个视频边上还是有点空白,黑色还相对可以忍受。
其实还有很多东西可以优化,比如监听触摸事件,通过滑动控制音量大小、亮度等。我当时就两个很简短的视频,没有在这上面花特别多心思,如果你项目视频较多的话当然是需要更进一步的优化的。还有给个小提示是个人开发者现在没办法发布带有视频的应用,我当时那个侥幸在应用宝、百度、和豌豆荚通过了,360就不行。
就到这了吧,还有些细节你们有兴趣的话可以看看我的源码,为了不误导大家又重新写了一遍顺便截图,有点累... 有错误的话请留言指正,谢谢!
源码下载