编程开源技术交流,分享技术与知识

网站首页 > 开源技术 正文

Android Vitamio使用篇,打造强悍的视频播放器

wxchong 2024-08-13 12:15:15 开源技术 18 ℃ 0 评论

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

Tags:

本文暂时没有评论,来添加一个吧(●'◡'●)

欢迎 发表评论:

最近发表
标签列表