Vitamio是一个优秀的Android视频框架,很多人也在用,所以这篇文章就是带大家接入Vitamio并且使用的
首先我们要明白一个需求就是,我们需要做一个视频播放器,那这样的话,我们首先想到的就是VideView,但是VideoView说实话,不支持很多视频格式,所以我们换成Vitamio,可以明确的说,Vitamio的使用方式基本上和VideoView是一样的,这也便于我们更好的封装
我们先看下他的官网:https://www.vitamio.org/
这些介绍我就不多BB了,直接点击下载中心可以看到,他提供了两个示例代码:
Android Vitamio演示(eclipse)
Android Vitamio演示(Android Studio)
我们首先推荐的也是Android Studio:https://github.com/yixia/VitamioBundleStudio
你只需要把代码下载下来,我们就可以开始集成了
一.集成踩坑
集成的话,还是万般简单的,你只需要解压下载下来的zip,我们是以 model 的方式集成,也就是vitamio这个包
然后再我们的Android Studio中,点击File - New - Import Model 即可
导入之后就开始我们得到踩坑之旅了
如果你发现无法集成model,你需要在在项目的settings.gradle里配置一下
include ':app',":vitamio"
然后在 app/build.gradle中配置如下
android{ defaultConfig{ ndk{ abiFilters 'armeabi', 'x86','armeabi-v7a' } } }
以及
//Vitamio implementation project(':vitamio')
相信这些都不是什么问题吧,紧接着我们要配置一下vitamio的build.gradle里
android { compileSdkVersion 28 //buildToolsVersion project.ANDROID_BUILD_TOOLS_VERSION defaultConfig { minSdkVersion 16 targetSdkVersion 22 } }
总的来讲就是需要配置
- compileSdkVersion
- minSdkVersion
- targetSdkVersion
至于这三个的版本号,你只需要和app/build.gradle保持一致就行,这里的一个坑就是targetSdkVersion 了,targetSdkVersion 必须<=22,不然某些机型会报错,至于什么原因,你自己去搜索下。
最后我们就可以配置清单文件了,在主工程的清单文件中添加如下:
<!--Vitamio--> <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" />
对了,记得配置权限:
<uses-permission android:name="android.permission.WAKE_LOCK" /> <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" /> <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" /> <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" /> <uses-permission android:name="android.permission.INTERNET" />
现在我们就可以开始封装了
二.封装Vitamio
使用方法跟VideoView一样,所以很好的封装
import android.net.Uri; import android.os.Handler; import android.os.Message; import com.xt.gtlauncher.utils.L; import io.vov.vitamio.MediaPlayer; import io.vov.vitamio.widget.VideoView; public class VideoManager { private io.vov.vitamio.widget.VideoView mVideoView; private OnVideoProgressListener listener; private static final int H_PROGRESS = 1001; private Handler mHandler = new Handler(new Handler.Callback() { @Override public boolean handleMessage(Message message) { switch (message.what) { case H_PROGRESS: if (listener != null) { //获取当前时长 long currentDuration = getCurrentPosition(); listener.onProgress(currentDuration); mHandler.sendEmptyMessageDelayed(H_PROGRESS, 1000); } break; } return false; } }); public VideoManager(VideoView mVideoView) { this.mVideoView = mVideoView; } /** * 设置文件路径 * * @param path */ public void setVideoPath(String path) { mVideoView.setVideoPath(path); } /** * 设置网络路径 * * @param uri */ public void setVideoURI(Uri uri) { mVideoView.setVideoURI(uri); } /** * 设置倍数 [0.5 - 2.0] * * @param mediaPlayer * @param speed */ public void setPlaybackSpeed(MediaPlayer mediaPlayer, float speed) { mediaPlayer.setPlaybackSpeed(speed); } /** * 获取当前播放的位置 * * @return */ public long getCurrentPosition() { return mVideoView.getCurrentPosition(); } /** * 获取当前的视频总长度 * * @return */ public long getDuration() { return mVideoView.getDuration(); } /** * 是否播放 * * @return */ public boolean isPlaying() { return mVideoView.isPlaying(); } /** * 播放 */ public void start() { mVideoView.start(); //mVideoView.requestFocus(); mHandler.sendEmptyMessage(H_PROGRESS); } /** * 暂停 */ public void pause() { mVideoView.pause(); } /** * 重新播放 */ public void resume() { mVideoView.resume(); } /** * 停止播放 释放资源 */ public void stopPlayback() { mVideoView.stopPlayback(); mHandler.removeMessages(H_PROGRESS); } /** * 从第几毫秒开始播放 * * @param msec */ public void seekTo(int msec) { mVideoView.seekTo(msec); } /** * 设置控制器 * * @param controller */ public void setMediaController(io.vov.vitamio.widget.MediaController controller) { mVideoView.setMediaController(controller); } /** * 监听播放完毕 * * @param l */ public void setOnCompletionListener(io.vov.vitamio.MediaPlayer.OnCompletionListener l) { mVideoView.setOnCompletionListener(l); } /** * 监听发生错误 * * @param l */ public void setOnErrorListener(io.vov.vitamio.MediaPlayer.OnErrorListener l) { mVideoView.setOnErrorListener(l); } /** * 监听视频装载完成 * * @param l */ public void setOnPreparedListener(io.vov.vitamio.MediaPlayer.OnPreparedListener l) { mVideoView.setOnPreparedListener(l); } /** * 监听进度 * * @param listener */ public void setOnVideoProgress(OnVideoProgressListener listener) { this.listener = listener; } public interface OnVideoProgressListener { void onProgress(long progress); } }
这里特别注意一下,我封装的过程中增加了进度的反馈,所以大家可以根据更方便的更新进度条
三.Vitamio的使用
先看下我的界面吧
<?xml version="1.0" encoding="utf-8"?> <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent"> <io.vov.vitamio.widget.VideoView android:id="@+id/mVideoView" android:layout_width="match_parent" android:layout_height="match_parent" /> <!--标题--> <LinearLayout android:gravity="center_vertical" android:orientation="horizontal" android:layout_width="match_parent" android:layout_height="wrap_content"> <ImageView android:id="@+id/iv_back" android:src="@mipmap/ic_launcher" android:layout_width="wrap_content" android:layout_height="wrap_content" /> <TextView android:text="--" android:id="@+id/tv_video_name" android:layout_width="wrap_content" android:layout_height="wrap_content" /> </LinearLayout> <!--控制--> <LinearLayout android:orientation="vertical" android:layout_alignParentBottom="true" android:layout_width="match_parent" android:layout_height="wrap_content"> <SeekBar android:thumb="@drawable/img_seekbar_tum" android:id="@+id/mSeekBar" android:layout_width="match_parent" android:layout_height="wrap_content" /> <LinearLayout android:gravity="center_vertical" android:layout_width="match_parent" android:layout_height="wrap_content" android:orientation="horizontal"> <ImageView android:id="@+id/iv_control" android:src="@mipmap/ic_launcher" android:layout_width="wrap_content" android:layout_height="wrap_content" /> <TextView android:text="--" android:id="@+id/tv_video_time" android:layout_width="wrap_content" android:layout_height="wrap_content" /> </LinearLayout> </LinearLayout> </RelativeLayout>
这个界面很简单,上面一个返回键和一个标题,下面一个控制键和一个时间显示
再来看下代码是如何实现的
import android.content.Intent;
import android.os.Bundle;
import android.view.View;
import android.widget.ImageView;
import android.widget.SeekBar;
import android.widget.TextView;
import io.vov.vitamio.Vitamio;
import io.vov.vitamio.widget.VideoView;
public class VideoActivity extends BaseActivity implements View.OnClickListener {
private VideoView mVideoView;
private TextView tv_video_name;
private SeekBar mSeekBar;
private TextView tv_video_time;
private ImageView iv_back;
private ImageView iv_control;
private VideoManager mVideoManager;
private String videoName;
private String videoPath;
private String videoAllDuration;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_video);
initView();
}
private void initView() {
Intent intent = getIntent();
videoName = intent.getStringExtra("name");
videoPath = intent.getStringExtra("path");
//Test
videoName = "Test";
videoPath = "/sdcard/Test.mp4";
mVideoView = (VideoView) findViewById(R.id.mVideoView);
tv_video_name = (TextView) findViewById(R.id.tv_video_name);
mSeekBar = (SeekBar) findViewById(R.id.mSeekBar);
tv_video_time = (TextView) findViewById(R.id.tv_video_time);
iv_back = (ImageView) findViewById(R.id.iv_back);
iv_control = (ImageView) findViewById(R.id.iv_control);
iv_control.setOnClickListener(this);
iv_back.setOnClickListener(this);
tv_video_name.setText(videoName);
initVideo();
}
private void initVideo() {
mVideoManager = new VideoManager(mVideoView);
mVideoManager.setVideoPath(videoPath);
mVideoManager.setOnPreparedListener(new io.vov.vitamio.MediaPlayer.OnPreparedListener() {
@Override
public void onPrepared(io.vov.vitamio.MediaPlayer mp) {
L.i("onPrepared");
mVideoManager.setPlaybackSpeed(mp, 1.0f);
long allDuration = mVideoManager.getDuration();
videoAllDuration = CommonUtils.formatDuring(allDuration);
mSeekBar.setMax((int) allDuration);
mVideoManager.start();
}
});
mVideoManager.setOnCompletionListener(new io.vov.vitamio.MediaPlayer.OnCompletionListener() {
@Override
public void onCompletion(io.vov.vitamio.MediaPlayer mediaPlayer) {
L.i("onCompletion");
}
});
mVideoManager.setOnVideoProgress(new VideoManager.OnVideoProgressListener() {
@Override
public void onProgress(long progress) {
mSeekBar.setProgress((int) progress);
tv_video_time.setText(CommonUtils.formatDuring(progress) + "/" + videoAllDuration);
}
});
mVideoManager.setOnErrorListener(new io.vov.vitamio.MediaPlayer.OnErrorListener() {
@Override
public boolean onError(io.vov.vitamio.MediaPlayer mediaPlayer, int i, int i1) {
L.e("i:" + i + "i1" + i1);
return false;
}
});
mSeekBar.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() {
@Override
public void onProgressChanged(SeekBar seekBar, int i, boolean b) {
}
@Override
public void onStartTrackingTouch(SeekBar seekBar) {
}
@Override
public void onStopTrackingTouch(SeekBar seekBar) {
mVideoManager.seekTo(mSeekBar.getProgress());
}
});
}
@Override
public void onClick(View view) {
switch (view.getId()) {
case R.id.iv_back:
finish();
break;
case R.id.iv_control:
if(mVideoManager.isPlaying()){
mVideoManager.pause();
}else{
mVideoManager.start();
}
break;
}
}
@Override
protected void onResume() {
super.onResume();
mVideoManager.resume();
}
@Override
protected void onPause() {
super.onPause();
mVideoManager.pause();
}
@Override
protected void onDestroy() {
super.onDestroy();
mVideoManager.stopPlayback();
}
}
这份代码可谓是很精简了,大概的流程我说下:
首先VideoManager初始化后设置路径,这里不光可以设置本地File路径也可以是网络路径,就需要setVideoURI即可。然后设置各种监听:
setOnPreparedListener设置就是当加载好视频之后的回调,这个时候我可以设置一下播放倍数,以及获取总时长和设置进度的总时长,然后开始播放视频
setOnCompletionListener 监听播放完成
setOnVideoProgress 不断通知刷新进度
setOnErrorListener 播放错误
setOnSeekBarChangeListener 进度条的拖拽 这里我调用了seekTo实现进度拖拽
最后绑定了一下生命周期即可了,这里用到了一个毫秒转换时长的方法
public class CommonUtils {
/**
* 毫秒转换成小时
* @param mss
* @return
*/
public static String formatDuring(long mss) {
long hours = (mss % (1000 * 60 * 60 * 24)) / (1000 * 60 * 60);
long minutes = (mss % (1000 * 60 * 60)) / (1000 * 60);
long seconds = (mss % (1000 * 60)) / 1000;
String h = "";
String m = "";
String s = "";
if(hours < 10){
h = "0" + hours;
}else{
h = hours + "";
}
if(minutes < 10){
m = "0" + minutes;
}else{
m = minutes + "";
}
if(seconds < 10){
s = "0" + seconds;
}else{
s = seconds + "";
}
return h + ":" + m + ":" + s;
}
}
到这里就本文就结束了,来看下最终的效果吧
欢迎加入交流群讨论:417046685
本文暂时没有评论,来添加一个吧(●'◡'●)