功能强大的Vitamio视频播放器教程

Vitamio简介:Vitamio是一个支持所有Android设备的多媒体框架。Vitamio与Android默认的MediaPlayer工作方式相似,但包含更加强大的功能!(注意:Vitamio商业化后个人免费、公司收费)

vitamio官网:https://www.vitamio.org

vitamio SDK地址:https://github.com/yixia/VitamioBundle

之前开发一个视频播放类的项目,需要实现在线播放的功能,找了很多视频播放框架,觉得Vitamio视频播放框架还不错,也相对稳定,但是在网上找了很多教程都少之又少,Vitamio官网写的教程也不是很清晰,所以就自己就把Vitamio在github上的demo进行研究,花了点时间写了个demo出来并且将Vitamio的视频控制器界面进行自定义,支持视频亮度、音量的调节,话不多说,先上效果图。

[附上 Demo的github地址](https://github.com/xiaohaibin/VitamioDemo)

                                   自定义视频控制器

![8F05796762EDAA5275D59EB31D3248E9.jpg](http://upload-images.jianshu.io/upload_images/1956769-182cab258d9a3b45.jpg?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)

目前,作者只实现了自定义手势调节亮度、音量的加减以及播放控制的功能,更多的功能等待着大家一起去挖掘。

使用步骤:

1.引入vitamio SDK的方式有两种:

(1)直接以module的方式引入

(2)通过Complie的方式引入

作者是采用的第一种方式,下面是一些需要注意的地方:

  • 清单文件配置:

1)权限设置:

```

```  

2)application配置:

```

<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" />

```

2.主要代码:

  • 播放视频代码

```

package com.stx.vitamiodemo;

import android.content.res.Configuration;

import android.net.Uri;

import android.os.Bundle;

import android.support.v7.app.AppCompatActivity;

import android.view.View;

import android.view.Window;

import android.view.WindowManager;

import android.widget.ProgressBar;

import android.widget.TextView;

import io.vov.vitamio.LibsChecker;

import io.vov.vitamio.MediaPlayer;

import io.vov.vitamio.Vitamio;

import io.vov.vitamio.widget.MediaController;

import io.vov.vitamio.widget.VideoView;

/**

 * Vitamio视频播放框架Demo

 */

public class MainActivity extends AppCompatActivity implements MediaPlayer.OnInfoListener, 

MediaPlayer.OnBufferingUpdateListener{

    //视频地址

    private String path = "http://baobab.wdjcdn.com/145076769089714.mp4";

    private Uri uri;

    private ProgressBar pb;

    private TextView downloadRateView, loadRateView;

    private MediaController mMediaController;

    private CustomMediaController mCustomMediaController;

    private VideoView mVideoView;

    @Override

    protected void onCreate(Bundle savedInstanceState) {

        super.onCreate(savedInstanceState);

        //定义全屏参数

        int flag = WindowManager.LayoutParams.FLAG_FULLSCREEN;

        //获得当前窗体对象

        Window window = MainActivity.this.getWindow();

        //设置当前窗体为全屏显示

        window.setFlags(flag, flag);

        //必须写这个,初始化加载库文件

        Vitamio.initialize(this);

        //设置视频解码监听

        if (!LibsChecker.checkVitamioLibs(this)) {

            return;

        }

        setContentView(R.layout.activity_main);

        initView();

        initData();

    }

    //初始化控件

    private void initView() {

        mVideoView = (VideoView) findViewById(R.id.buffer);

        mMediaController= new MediaController(this);

        mCustomMediaController=new CustomMediaController(this,mVideoView,this);

        mCustomMediaController.setVideoName("白火锅 x 红火锅");

        pb = (ProgressBar) findViewById(R.id.probar);

        downloadRateView = (TextView) findViewById(R.id.download_rate);

        loadRateView = (TextView) findViewById(R.id.load_rate);

    }

    //初始化数据

    private void initData() {

        uri = Uri.parse(path);

        mVideoView.setVideoURI(uri);//设置视频播放地址

        mVideoView.setMediaController(mCustomMediaController);

        mVideoView.setVideoQuality(MediaPlayer.VIDEOQUALITY_HIGH);//高画质

        mMediaController.show(5000);

        mVideoView.requestFocus();

        mVideoView.setOnInfoListener(this);

        mVideoView.setOnBufferingUpdateListener(this);

        mVideoView.setOnPreparedListener(new MediaPlayer.OnPreparedListener() {

            @Override

            public void onPrepared(MediaPlayer mediaPlayer) {

                mediaPlayer.setPlaybackSpeed(1.0f);

            }

        });

    }

    @Override

    public boolean onInfo(MediaPlayer mp, int what, int extra) {

        switch (what) {

            case MediaPlayer.MEDIA_INFO_BUFFERING_START:

                if (mVideoView.isPlaying()) {

                    mVideoView.pause();

                    pb.setVisibility(View.VISIBLE);

                    downloadRateView.setText("");

                    loadRateView.setText("");

                    downloadRateView.setVisibility(View.VISIBLE);

                    loadRateView.setVisibility(View.VISIBLE);

                }

                break;

            case MediaPlayer.MEDIA_INFO_BUFFERING_END:

                mVideoView.start();

                pb.setVisibility(View.GONE);

                downloadRateView.setVisibility(View.GONE);

                loadRateView.setVisibility(View.GONE);

                break;

            case MediaPlayer.MEDIA_INFO_DOWNLOAD_RATE_CHANGED:

                downloadRateView.setText("" + extra + "kb/s" + "  ");

                break;

        }

        return true;

    }

    @Override

    public void onBufferingUpdate(MediaPlayer mp, int percent) {

        loadRateView.setText(percent + "%");

    }

    @Override

    public void onConfigurationChanged(Configuration newConfig) {

        //屏幕切换时,设置全屏

        if (mVideoView != null){

            mVideoView.setVideoLayout(VideoView.VIDEO_LAYOUT_SCALE, 0);

        }

        super.onConfigurationChanged(newConfig);

    }

}

```

  • 自定义视频控制器:

主要实现了手势调节视频亮度、音量的加减控制。

```

package com.stx.vitamiodemo;

import android.app.Activity;

import android.content.Context;

import android.media.AudioManager;

import android.os.Handler;

import android.os.Message;

import android.view.Display;

import android.view.GestureDetector;

import android.view.KeyEvent;

import android.view.LayoutInflater;

import android.view.MotionEvent;

import android.view.View;

import android.view.WindowManager;

import android.widget.ImageButton;

import android.widget.ImageView;

import android.widget.RelativeLayout;

import android.widget.SeekBar;

import android.widget.TextView;

import io.vov.vitamio.widget.MediaController;

import io.vov.vitamio.widget.VideoView;

/**

 * Created by xhb on 2016/3/1.

 * 自定义视频控制器

 */

public class CustomMediaController extends MediaController {

    private static final int HIDEFRAM = 0;//控制提示窗口的显示

    private GestureDetector mGestureDetector;

    private ImageButton img_back;//返回按钮

    private TextView mFileName;//文件名

    private VideoView videoView;

    private Activity activity;

    private Context context;

    private String videoname;//视频名称

    private int controllerWidth = 0;//设置mediaController高度为了使横屏时top显示在屏幕顶端

    private View mVolumeBrightnessLayout;//提示窗口

    private ImageView mOperationBg;//提示图片

    private TextView mOperationTv;//提示文字

    private AudioManager mAudioManager;

    private SeekBar progress;

    private boolean mDragging;

    private MediaPlayerControl player;

    //最大声音

    private int mMaxVolume;

    // 当前声音

    private int mVolume = -1;

    //当前亮度

    private float mBrightness = -1f;

    //返回监听

    private View.OnClickListener backListener = new View.OnClickListener() {

        public void onClick(View v) {

            if (activity != null) {

                activity.finish();

            }

        }

    };

    private Handler myHandler = new Handler() {

        @Override

        public void handleMessage(Message msg) {

            long pos;

            switch (msg.what) {

                case HIDEFRAM://隐藏提示窗口

                    mVolumeBrightnessLayout.setVisibility(View.GONE);

                    mOperationTv.setVisibility(View.GONE);

                    break;

            }

        }

    };

    //videoview 用于对视频进行控制的等,activity为了退出

    public CustomMediaController(Context context, VideoView videoView, Activity activity) {

        super(context);

        this.context = context;

        this.videoView = videoView;

        this.activity = activity;

        WindowManager wm = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);

        controllerWidth = wm.getDefaultDisplay().getWidth();

        mGestureDetector = new GestureDetector(context, new MyGestureListener());

    }

    @Override

    protected View makeControllerView() {

        //此处的   mymediacontroller  为我们自定义控制器的布局文件名称

        View v = ((LayoutInflater) getContext().getSystemService(Context.LAYOUT_INFLATER_SERVICE)).inflate

(getResources().getIdentifier("mymediacontroller", "layout", getContext().getPackageName()), this);

        v.setMinimumHeight(controllerWidth);

        //获取控件

        img_back = (ImageButton) v.findViewById(getResources().getIdentifier("mediacontroller_top_back", "id", 

context.getPackageName()));

        mFileName = (TextView) v.findViewById(getResources().getIdentifier("mediacontroller_filename", "id", 

context.getPackageName()));

        if (mFileName != null) {

            mFileName.setText(videoname);

        }

        //声音控制

        mVolumeBrightnessLayout = (RelativeLayout) v.findViewById(R.id.operation_volume_brightness);

        mOperationBg = (ImageView) v.findViewById(R.id.operation_bg);

        mOperationTv = (TextView) v.findViewById(R.id.operation_tv);

        mOperationTv.setVisibility(View.GONE);

        mAudioManager = (AudioManager) context.getSystemService(Context.AUDIO_SERVICE);

        mMaxVolume = mAudioManager

                .getStreamMaxVolume(AudioManager.STREAM_MUSIC);

        //注册事件监听

        img_back.setOnClickListener(backListener);

        return v;

    }

    @Override

    public boolean dispatchKeyEvent(KeyEvent event) {

        System.out.println("MYApp-MyMediaController-dispatchKeyEvent");

        return true;

    }

    @Override

    public boolean onTouchEvent(MotionEvent event) {

        if (mGestureDetector.onTouchEvent(event)) return true;

        // 处理手势结束

        switch (event.getAction() & MotionEvent.ACTION_MASK) {

            case MotionEvent.ACTION_UP:

                endGesture();

                break;

        }

        return super.onTouchEvent(event);

    }

    /**

     * 手势结束

     */

    private void endGesture() {

        mVolume = -1;

        mBrightness = -1f;

        // 隐藏

        myHandler.removeMessages(HIDEFRAM);

        myHandler.sendEmptyMessageDelayed(HIDEFRAM, 1);

    }

    private class MyGestureListener extends GestureDetector.SimpleOnGestureListener {

        @Override

        public boolean onSingleTapUp(MotionEvent e) {

            return false;

        }

        /**

         * 因为使用的是自定义的mediaController 当显示后,mediaController会铺满屏幕,

         * 所以VideoView的点击事件会被拦截,所以重写控制器的手势事件,

         * 将全部的操作全部写在控制器中,

         * 因为点击事件被控制器拦截,无法传递到下层的VideoView,

         * 所以 原来的单机隐藏会失效,作为代替,

         * 在手势监听中onSingleTapConfirmed()添加自定义的隐藏/显示,

         *

         * @param e

         * @return

         */

        @Override

        public boolean onSingleTapConfirmed(MotionEvent e) {

            //当手势结束,并且是单击结束时,控制器隐藏/显示

            toggleMediaControlsVisiblity();

            return super.onSingleTapConfirmed(e);

        }

        @Override

        public boolean onDown(MotionEvent e) {

            return true;

        }

        //滑动事件监听

        @Override

        public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX, float distanceY) {

            float mOldX = e1.getX(), mOldY = e1.getY();

            int y = (int) e2.getRawY();

            int x = (int) e2.getRawX();

            Display disp = activity.getWindowManager().getDefaultDisplay();

            int windowWidth = disp.getWidth();

            int windowHeight = disp.getHeight();

            if (mOldX > windowWidth * 3.0 / 4.0) {// 右边滑动 屏幕 3/4

                onVolumeSlide((mOldY - y) / windowHeight);

            } else if (mOldX < windowWidth * 1.0 / 4.0) {// 左边滑动 屏幕 1/4

                onBrightnessSlide((mOldY - y) / windowHeight);

            }

            return super.onScroll(e1, e2, distanceX, distanceY);

        }

        @Override

        public boolean onDoubleTap(MotionEvent e) {

            playOrPause();

            return true;

        }

        @Override

        public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) {

            return super.onFling(e1, e2, velocityX, velocityY);

        }

    }

    /**

     * 滑动改变声音大小

     *

     * @param percent

     */

    private void onVolumeSlide(float percent) {

        if (mVolume == -1) {

            mVolume = mAudioManager.getStreamVolume(AudioManager.STREAM_MUSIC);

            if (mVolume < 0)

                mVolume = 0;

            // 显示

            mVolumeBrightnessLayout.setVisibility(View.VISIBLE);

            mOperationTv.setVisibility(VISIBLE);

        }

        int index = (int) (percent * mMaxVolume) + mVolume;

        if (index > mMaxVolume)

            index = mMaxVolume;

        else if (index < 0)

            index = 0;

        if (index >= 10) {

            mOperationBg.setImageResource(R.drawable.volmn_100);

        } else if (index >= 5 && index < 10) {

            mOperationBg.setImageResource(R.drawable.volmn_60);

        } else if (index > 0 && index < 5) {

            mOperationBg.setImageResource(R.drawable.volmn_30);

        } else {

            mOperationBg.setImageResource(R.drawable.volmn_no);

        }

        //DecimalFormat    df   = new DecimalFormat("######0.00");

        mOperationTv.setText((int) (((double) index / mMaxVolume) * 100) + "%");

        // 变更声音

        mAudioManager.setStreamVolume(AudioManager.STREAM_MUSIC, index, 0);

    }

    /**

     * 滑动改变亮度

     *

     * @param percent

     */

    private void onBrightnessSlide(float percent) {

        if (mBrightness < 0) {

            mBrightness = activity.getWindow().getAttributes().screenBrightness;

            if (mBrightness <= 0.00f)

                mBrightness = 0.50f;

            if (mBrightness < 0.01f)

                mBrightness = 0.01f;

            // 显示

            mVolumeBrightnessLayout.setVisibility(View.VISIBLE);

            mOperationTv.setVisibility(VISIBLE);

        }

        WindowManager.LayoutParams lpa = activity.getWindow().getAttributes();

        lpa.screenBrightness = mBrightness + percent;

        if (lpa.screenBrightness > 1.0f)

            lpa.screenBrightness = 1.0f;

        else if (lpa.screenBrightness < 0.01f)

            lpa.screenBrightness = 0.01f;

        activity.getWindow().setAttributes(lpa);

        mOperationTv.setText((int) (lpa.screenBrightness * 100) + "%");

        if (lpa.screenBrightness * 100 >= 90) {

            mOperationBg.setImageResource(R.drawable.light_100);

        } else if (lpa.screenBrightness * 100 >= 80 && lpa.screenBrightness * 100 < 90) {

            mOperationBg.setImageResource(R.drawable.light_90);

        } else if (lpa.screenBrightness * 100 >= 70 && lpa.screenBrightness * 100 < 80) {

            mOperationBg.setImageResource(R.drawable.light_80);

        } else if (lpa.screenBrightness * 100 >= 60 && lpa.screenBrightness * 100 < 70) {

            mOperationBg.setImageResource(R.drawable.light_70);

        } else if (lpa.screenBrightness * 100 >= 50 && lpa.screenBrightness * 100 < 60) {

            mOperationBg.setImageResource(R.drawable.light_60);

        } else if (lpa.screenBrightness * 100 >= 40 && lpa.screenBrightness * 100 < 50) {

            mOperationBg.setImageResource(R.drawable.light_50);

        } else if (lpa.screenBrightness * 100 >= 30 && lpa.screenBrightness * 100 < 40) {

            mOperationBg.setImageResource(R.drawable.light_40);

        } else if (lpa.screenBrightness * 100 >= 20 && lpa.screenBrightness * 100 < 20) {

            mOperationBg.setImageResource(R.drawable.light_30);

        } else if (lpa.screenBrightness * 100 >= 10 && lpa.screenBrightness * 100 < 20) {

            mOperationBg.setImageResource(R.drawable.light_20);

        }

    }

    /**

     * 设置视频文件名

     *

     * @param name

     */

    public void setVideoName(String name) {

        videoname = name;

        if (mFileName != null) {

            mFileName.setText(name);

        }

    }

    /**

     * 隐藏或显示

     */

    private void toggleMediaControlsVisiblity() {

        if (isShowing()) {

            hide();

        } else {

            show();

        }

    }

    /**

     * 播放/暂停

     */

    private void playOrPause() {

        if (videoView != null)

            if (videoView.isPlaying()) {

                videoView.pause();

            } else {

                videoView.start();

            }

    }

}

```

 - 自定义控制器布局文件:

```

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"    

android:orientation="vertical"    

android:layout_width="match_parent"    

android:background="@drawable/video_player_bg_color"    

android:layout_height="match_parent">    

<RelativeLayout        

android:layout_width="match_parent"        

android:layout_height="match_parent">        

<RelativeLayout            

android:layout_width="match_parent"            

android:background="#77000000"            

android:layout_height="34dp">            

<ImageButton                

android:id="@+id/mediacontroller_top_back"                

android:layout_width="50dp"                

android:layout_height="match_parent"                

android:layout_alignParentLeft="true"                

android:background="@null"                

android:src="@drawable/ic_player_close_white"/>            

<TextView                

android:id="@+id/mediacontroller_filename"                

style="@style/MediaController_Text"                

android:layout_width="wrap_content"                

android:layout_height="wrap_content"                

android:layout_centerVertical="true"                

android:layout_marginLeft="5dp"                

android:layout_toRightOf="@+id/mediacontroller_top_back"                

android:ellipsize="marquee"                

android:singleLine="true"               

android:text="file name"/>            

<ImageButton                

android:id="@+id/mediacontroller_share"                

android:layout_width="50dp"                

android:layout_height="match_parent"                

android:background="@null"                

android:src="@drawable/ic_action_share_without_padding"                

android:layout_alignParentRight="true"/>            

<ImageButton                

android:id="@+id/mediacontroller_favorite"                

android:layout_width="50dp"                

android:layout_height="match_parent"                

android:background="@null"                

android:layout_toLeftOf="@id/mediacontroller_share"                

android:src="@drawable/ic_action_favorites"/>        

       

<ImageButton            

android:id="@+id/mediacontroller_play_pause"            

android:layout_width="wrap_content"            

android:layout_height="wrap_content"            

android:layout_centerInParent="true"            

android:src="@drawable/paly_selector"            

android:background="@null"/>        

<RelativeLayout            

android:id="@+id/operation_volume_brightness"            

android:layout_width="150dp"            

android:layout_height="75dp"            

android:layout_centerInParent="true"            

android:background="@drawable/videobg"            

android:orientation="horizontal"            

android:padding="0dip"            

android:visibility="gone">            

<ImageView                

android:id="@+id/operation_bg"                

android:layout_width="wrap_content"                

android:layout_height="wrap_content"                

android:layout_centerInParent="true"                

android:src="@drawable/video_volumn_bg"/>            

<TextView                

android:id="@+id/operation_tv"                

android:layout_width="wrap_content"                

android:layout_height="wrap_content"                

android:layout_alignBottom="@+id/operation_bg"                

android:layout_centerHorizontal="true"                

android:layout_alignParentBottom ="true"                

android:text="32:22/45:00"                

android:textColor="#ffffff"                

android:textSize="10sp"                

android:visibility="gone"               

/>        

       

<RelativeLayout            

android:layout_width="match_parent"            

android:layout_alignParentBottom="true"            

android:background="#77000000"            

android:layout_height="50dp">            

<TextView                

android:id="@+id/mediacontroller_time_current"                

style="@style/MediaController_Text"                

android:layout_width="wrap_content"                

android:layout_height="wrap_content"                

android:layout_centerVertical="true"                

android:layout_marginLeft="15dp"                

android:text="33:33:33"                

/>            

<TextView                

android:id="@+id/mediacontroller_time_total"                

style="@style/MediaController_Text"                

android:layout_width="wrap_content"                

android:layout_height="wrap_content"                

android:layout_alignParentRight="true"                

android:layout_centerVertical="true"                

android:layout_marginRight="15dp"                

android:text="33:33:33"/>            

<SeekBar                

android:id="@+id/mediacontroller_seekbar"                

style="@style/MediaController_SeekBar"                

android:layout_width="match_parent"                

android:layout_height="wrap_content"                

android:layout_centerVertical="true"                

android:layout_toLeftOf="@id/mediacontroller_time_total"                

android:layout_toRightOf="@id/mediacontroller_time_current"                

android:focusable="true"                

android:max="1000"/>        

   

```

  • 视频播放界面布局:

```

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"    

android:layout_width="match_parent"    

android:layout_height="match_parent">    

<io.vov.vitamio.widget.CenterLayout        

android:layout_width="match_parent"        

android:layout_height="match_parent"        

android:orientation="vertical">        

<io.vov.vitamio.widget.VideoView            

android:id="@+id/buffer"            

android:layout_width="match_parent"            

android:layout_height="match_parent"            

android:layout_centerHorizontal="true"            

android:layout_centerVertical="true" />    

</io.vov.vitamio.widget.CenterLayout>    

<LinearLayout        

android:layout_width="wrap_content"        

android:layout_height="wrap_content"        

android:layout_centerInParent="true"        

android:orientation="horizontal">        

<ProgressBar            

android:id="@+id/probar"            

style="?android:attr/progressBarStyleLarge"            

android:layout_width="50dp"            

android:layout_height="50dp" />        

<TextView            

android:id="@+id/download_rate"            

android:layout_width="wrap_content"            

android:layout_height="wrap_content"            

android:layout_gravity="center"            

android:textColor="#FFFFFF"           

android:text="" />        

<TextView            

android:id="@+id/load_rate"            

android:layout_width="wrap_content"            

android:layout_height="wrap_content"            

android:layout_gravity="center"            

android:textColor="#FFFFFF"            

android:text="" />    

```

[github地址](https://github.com/xiaohaibin/VitamioDemo)

写的不好之处还望大家见谅。、