开源全能播放器Vitamio的使用
原文鏈接:簡書@jxnk25,http://www.jianshu.com/p/d50a67ba253c
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的視頻控制器界面進行自定義,支持視頻亮度、音量的調節,話不多說,先上效果圖。
自定義視頻控制器
目前,作者只實現了自定義手勢調節亮度、音量的加減以及播放控制的功能,更多的功能等待著大家一起去挖掘。
使用步驟
1、引入vitamio SDK的方式有兩種:
- 直接以module的方式引入
- 通過Complie的方式引入
作者是采用的第一種方式,下面是一些需要注意的地方:
清單文件配置,權限設置:
<uses-permission android:name="android.permission.WAKE_LOCK" /> <uses-permission android:name="android.permission.INTERNET" /> <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" /> <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />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" />主要代碼
播放視頻代碼
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;@Overrideprotected 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() {@Overridepublic void onPrepared(MediaPlayer mediaPlayer) {mediaPlayer.setPlaybackSpeed(1.0f);}});}@Overridepublic 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;}@Overridepublic void onBufferingUpdate(MediaPlayer mp, int percent) {loadRateView.setText(percent + "%");}@Overridepublic 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() {@Overridepublic 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());}@Overrideprotected 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;}@Overridepublic boolean dispatchKeyEvent(KeyEvent event) {System.out.println("MYApp-MyMediaController-dispatchKeyEvent");return true;}@Overridepublic 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 {@Overridepublic boolean onSingleTapUp(MotionEvent e) {return false;}/*** 因為使用的是自定義的mediaController 當顯示后,mediaController會鋪滿屏幕,* 所以VideoView的點擊事件會被攔截,所以重寫控制器的手勢事件,* 將全部的操作全部寫在控制器中,* 因為點擊事件被控制器攔截,無法傳遞到下層的VideoView,* 所以 原來的單機隱藏會失效,作為代替,* 在手勢監聽中onSingleTapConfirmed()添加自定義的隱藏/顯示,** @param e* @return*/@Overridepublic boolean onSingleTapConfirmed(MotionEvent e) {//當手勢結束,并且是單擊結束時,控制器隱藏/顯示toggleMediaControlsVisiblity();return super.onSingleTapConfirmed(e);}@Overridepublic boolean onDown(MotionEvent e) {return true;}//滑動事件監聽@Overridepublic 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/4onVolumeSlide((mOldY - y) / windowHeight);} else if (mOldX < windowWidth * 1.0 / 4.0) {// 左邊滑動 屏幕 1/4onBrightnessSlide((mOldY - y) / windowHeight);}return super.onScroll(e1, e2, distanceX, distanceY);}@Overridepublic boolean onDoubleTap(MotionEvent e) {playOrPause();return true;}@Overridepublic 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();}}}自定義控制器布局文件
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"android:layout_width="match_parent"android:layout_height="match_parent"android:background="@drawable/video_player_bg_color"android:orientation="vertical"><RelativeLayout android:layout_width="match_parent"android:layout_height="match_parent"><RelativeLayout android:layout_width="match_parent"android:layout_height="34dp"android:background="#77000000"><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:layout_alignParentRight="true"android:background="@null"android:src="@drawable/ic_action_share_without_padding"/><ImageButton android:id="@+id/mediacontroller_favorite"android:layout_width="50dp"android:layout_height="match_parent"android:layout_toLeftOf="@id/mediacontroller_share"android:background="@null"android:src="@drawable/ic_action_favorites"/></RelativeLayout><ImageButton android:id="@+id/mediacontroller_play_pause"android:layout_width="wrap_content"android:layout_height="wrap_content"android:layout_centerInParent="true"android:background="@null"android:src="@drawable/paly_selector"/><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_alignParentBottom="true"android:layout_centerHorizontal="true"android:text="32:22/45:00"android:textColor="#ffffff"android:textSize="10sp"android:visibility="gone"/></RelativeLayout><RelativeLayout android:layout_width="match_parent"android:layout_height="50dp"android:layout_alignParentBottom="true"android:background="#77000000"><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></RelativeLayout> </LinearLayout>視頻播放界面布局
<?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.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:text=""android:textColor="#FFFFFF"/><TextView android:id="@+id/load_rate"android:layout_width="wrap_content"android:layout_height="wrap_content"android:layout_gravity="center"android:text=""android:textColor="#FFFFFF"/></LinearLayout> </RelativeLayout>Vitamio Demo Github地址
總結
以上是生活随笔為你收集整理的开源全能播放器Vitamio的使用的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Could not get unknow
- 下一篇: requestWindowFeature