首页 > 移动平台 > 详细

Android本地文件点击视频播放器vitamio版

时间:2016-07-16 23:44:24      阅读:603      评论:0      收藏:0      [点我收藏+]

本博客用Android studio集成了vitamio的自定义视频播放器,同时可以在文件管理中选择播放,想要一个自己的视频播放器这边便可以满足

实现具体功能如下:

1.sd卡内存视频文件的点击播放;

2.视频时间进度条;

3.屏幕亮度的手势滑动;

4.视频音量的手势滑动;

5.多点手势效果

6.自定义存储视频url播放

技术分享

技术分享



想要的重要的代码,我懂得:

------------------------------软件工程结构图:

技术分享

最重要的是依赖上vitamio库:

技术分享

-------------------------工具类FileUtil,检查文件格式是否属于自己定义的格式:

public class FileUtil {
	public static final String[] VIDEO_EXTENSIONS = {  "3gp", "amv",
			"avb", "avd", "avi", "flh", "fli", "flv", "flx", "gvi", "gvp",
			"hdmov", "hkm", "ifo", "imovi", "imovi", "iva", "ivf", "ivr",
			"m4v", "m75", "meta", "mgv", "mj2", "mjp", "mjpg", "mkv", "mmv",
			"mnv", "mod", "modd", "moff", "moi", "moov", "mov", "movie",
			"mp21", "mp21", "mp2v", "mp4", "mp4v", "mpe", "mpeg", "mpeg4",
			"mpf", "mpg", "mpg2", "mpgin", "mpl", "mpls", "mpv", "mpv2", "mqv",
			"msdvd", "msh", "mswmm", "mts", "mtv", "mvb", "mvc", "mvd", "mve",
			"mvp", "mxf", "mys", "ncor", "nsv", "nvc", "ogm", "ogv", "ogx",
			"osp", "par", "pds", "pgi", "piv", "playlist", "pmf", "prel",
			"pro", "prproj", "psh", "pva", "pvr", "pxv", "qt", "qtch", "qtl",
			"qtm", "qtz", "rcproject", "rdb", "rec", "rm", "rmd", "rmp", "rms",
			"rmvb", "roq", "rp", "rts", "rts", "rum", "rv", "sbk", "sbt",
			"scm", "scm", "scn", "sec", "seq", "sfvidcap", "smil", "smk",
			"sml", "smv", "spl", "ssm", "str", "stx", "svi", "swf", "swi",
			"swt", "tda3mt", "tivo", "tix", "tod", "tp", "tp0", "tpd", "tpr",
			"trp", "ts", "tvs", "vc1", "vcr", "vcv", "vdo", "vdr", "veg",
			"vem", "vf", "vfw", "vfz", "vgz", "vid", "viewlet", "viv", "vivo",
			 "wma"
		};
	//集合放置所有支持视频格式
	private static final List<String> listvideo = new ArrayList<>(
			Arrays.asList(VIDEO_EXTENSIONS));

	// 检测是否是视频文件
	public static boolean isVideo(String path) {
		path=getFileExtension(path);
		return listvideo.contains(path);
	}
	//	 获取文件后缀名
	public static String getFileExtension(String path) {
		if (null != path) {
			// 后缀点 的位置
			int dex = path.lastIndexOf(".");
			// 截取后缀名
			return path.substring(dex + 1);
		}
		return null;
	}
}
--------------------工具类FileUtil,检查文件格式是否属于自己定义的格式:

public class LocUtil {
// 获取所有存储路径
	public static List<String> getDirs(Context context) {
		List<String> dirs = new ArrayList<String>();
		StorageManager storageManager = (StorageManager) context
				.getSystemService(Context.STORAGE_SERVICE);
		try {
			Class[] paramClasses = {};
			Method getVolumePathsMethod = StorageManager.class.getMethod(
					"getVolumePaths", paramClasses);
			getVolumePathsMethod.setAccessible(true);
			Object[] params = {};
			Object invoke = getVolumePathsMethod.invoke(storageManager, params);
			for (int i = 0; i < ((String[]) invoke).length; i++) {
				// System.out.println(((String[])invoke)[i]);
				dirs.add(((String[]) invoke)[i]);
			}
		} catch (Exception e) {
			e.printStackTrace();
		}
		return dirs;
	}
	//获取最大音量
	public static int getMaxVolume(Context context) {
		return ((AudioManager) context.getSystemService(Context.AUDIO_SERVICE))
				.getStreamMaxVolume(AudioManager.STREAM_MUSIC);
	}
	 // 获取当前音量
	public static int getCurVolume(Context context) {
		return ((AudioManager) context.getSystemService(Context.AUDIO_SERVICE))
				.getStreamVolume(AudioManager.STREAM_MUSIC);
	}
	// 设置当前音量
	public static void setCurVolume(Context context, int index) {
		((AudioManager) context.getSystemService(Context.AUDIO_SERVICE))
				.setStreamVolume(AudioManager.STREAM_MUSIC, index, 0);
	}
//	 获取屏幕像素
	public static ScreenBean getScreenPix(Context context) {
		Display dplay = ((VideoPlay) context).getWindowManager()
				.getDefaultDisplay();
		return new ScreenBean(dplay.getWidth(),dplay.getHeight());
	}
}

-------------实体类屏幕的宽高ScreenBean,保存视频宽高:
public class ScreenBean {
	private int sWidth;
	private int sHeight;
	public ScreenBean(int sWidth, int sHeight) {
		super();
		this.sWidth = sWidth;
		this.sHeight = sHeight;
	}
	public int getsWidth() {
		return sWidth;
	}
	public void setsWidth(int sWidth) {
		this.sWidth = sWidth;
	}
	public int getsHeight() {
		return sHeight;
	}
	public void setsHeight(int sHeight) {
		this.sHeight = sHeight;
	}
}
----------------------中转传递界面MainActivity类:

public class MainActivity extends AppCompatActivity {
    String Path;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        Intent getPath=getIntent();
        String action = getPath.getAction();
        if(getPath.ACTION_VIEW.equals(action)){
            Path=getPath.getDataString();
        }else {
            Path= Environment.getExternalStorageDirectory() + "/test.mp4";
        }
       Intent intent = new Intent(this, VideoPlay.class);
        intent.putExtra("videoURL",Path);
        startActivity(intent);
        finish();
 }
}
这个界面是中转,开发时一般自己定义,

Path=getPath.getDataString();//获取sd卡的视频文件url路径
Path= Environment.getExternalStorageDirectory() + "/test.mp4";
//程序存储的路径,可以扫描手机内存视频存储到数据库,这种视频列表简单自己写.

----------------------视频播放Activity类:

public class VideoPlay extends Activity {
	/** 当前视频路径 */
	private String path;
	/** 当前声音 */
	private int mVolume = -1;
	/** 最大音量 */
	private int mMaxVolume;
	/** 当前亮度 */
	private float mBrightness = -1f;
	/** 手势数目 */
	private int finNum=0;
	
	private View mVolumeBrightnessLayout;
	private ImageView mOperationBg;
	private ImageView mOperationPercent;
	private VideoView mVideoView;
	private GestureDetector gestDetector;
	private ScaleGestureDetector scaleDetector;

	private ScreenBean screenBean;

	@Override
	public void onCreate(Bundle icicle) {
		super.onCreate(icicle);
		if (!LibsChecker.checkVitamioLibs(this))
			return;

		requestWindowFeature(Window.FEATURE_NO_TITLE);
		setContentView(R.layout.activity_video);
		Intent getPath=getIntent();
		path=getPath.getStringExtra("videoURL");

		init();
	}

	private void init() {

		mVideoView = (VideoView) findViewById(R.id.surface_view);
		mVolumeBrightnessLayout = findViewById(R.id.operation_volume_brightness);
		mOperationBg = (ImageView) findViewById(R.id.operation_bg);
		mOperationPercent = (ImageView) findViewById(R.id.operation_percent);

		mMaxVolume = LocUtil.getMaxVolume(this);
		gestDetector = new GestureDetector(this, new SingleGestureListener());
		scaleDetector = new ScaleGestureDetector(this,
				new MultiGestureListener());

		screenBean = LocUtil.getScreenPix(this);
		if (path == "") {
			return;
		} else {
			mVideoView.setVideoPath(path);
			mVideoView.setMediaController(new MediaController(this));
			mVideoView.requestFocus();

			mVideoView.setOnPreparedListener(new MediaPlayer.OnPreparedListener() {
						@Override
						public void onPrepared(MediaPlayer mediaPlayer) {
							mediaPlayer.setPlaybackSpeed(1.0f);
						}
					});
		}
	}

	/** 定时隐藏 */
	private Handler mDismissHandler = new Handler() {
		@Override
		public void handleMessage(Message msg) {
			mVolumeBrightnessLayout.setVisibility(View.GONE);
		}
	};

	@Override
	public boolean onTouchEvent(MotionEvent event) {
		// TODO Auto-generated method stub
		finNum=event.getPointerCount();

		if (1 == finNum) {
			gestDetector.onTouchEvent(event);
			switch (event.getAction()) {
			case MotionEvent.ACTION_UP:
				endGesture();
			}
		} else if (2 ==finNum) {
			scaleDetector.onTouchEvent(event);
		}
		return true;
	}

	/** 手势结束 */
	private void endGesture() {
		mVolume = -1;
		mBrightness = -1f;

		// 隐藏
		mDismissHandler.removeMessages(0);
		mDismissHandler.sendEmptyMessageDelayed(0, 500);
	}

	/**
	 * 视频缩放
	 */
	public void changeLayout(int size) {
		mVideoView.setVideoLayout(size, 0);
	}

	/**
	 * 声音大小
	 *
	 */
	public void changeVolume(float percent) {
		if (mVolume == -1) {
			mVolume = LocUtil.getCurVolume(this);
			if (mVolume < 0)
				mVolume = 0;
			// 显示
			mOperationBg.setImageResource(R.drawable.video_volumn_bg);
			mVolumeBrightnessLayout.setVisibility(View.VISIBLE);
		}
		int index = (int) (percent * mMaxVolume) + mVolume;
		if (index > mMaxVolume)
			index = mMaxVolume;
		else if (index < 0)
			index = 0;

		// 变更声音
		LocUtil.setCurVolume(this, index);

		// 变更进度条
		ViewGroup.LayoutParams lp = mOperationPercent.getLayoutParams();
		lp.width = findViewById(R.id.operation_full).getLayoutParams().width
				* index / mMaxVolume;
		mOperationPercent.setLayoutParams(lp);
	}

	/**
	 * 亮度大小
	 * 
	 * @param percent
	 */
	public void changeBrightness(float percent) {
		if (mBrightness < 0) {
			mBrightness = getWindow().getAttributes().screenBrightness;
			if (mBrightness <= 0.00f)
				mBrightness = 0.50f;
			if (mBrightness < 0.01f)
				mBrightness = 0.01f;
			// 显示
			mOperationBg.setImageResource(R.drawable.video_brightness_bg);
			mVolumeBrightnessLayout.setVisibility(View.VISIBLE);
		}

		WindowManager.LayoutParams lpa = 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;
		getWindow().setAttributes(lpa);

		ViewGroup.LayoutParams lp = mOperationPercent.getLayoutParams();
		lp.width = (int) (findViewById(R.id.operation_full).getLayoutParams().width * lpa.screenBrightness);
		mOperationPercent.setLayoutParams(lp);
	}

	/**
	 * 单点触屏
	 */
	private class SingleGestureListener implements
			GestureDetector.OnGestureListener {

		@Override
		public boolean onDown(MotionEvent e) {
			// TODO Auto-generated method stub
			return false;
		}

		@Override
		public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX,
				float velocityY) {
			// TODO Auto-generated method stub
			Log.d("Fling", velocityY);
			return false;
		}

		@Override
		public void onLongPress(MotionEvent e) {
			// TODO Auto-generated method stub

		}

		@Override
		public boolean onScroll(MotionEvent e1, MotionEvent e2,
				float distanceX, float distanceY) {
			// TODO Auto-generated method stub
			if(2==finNum){
				return false;
			}
			
			float moldX = e1.getX();
			float moldY = e1.getY();
			float y = e2.getY();
			if (moldX > screenBean.getsWidth() * 9.0 / 10)// 右边滑动
				changeVolume((moldY - y) / screenBean.getsHeight());
			else if (moldX < screenBean.getsWidth() / 10.0)// 左边滑动
				changeBrightness((moldY - y) / screenBean.getsHeight());
			return false;
		}

		@Override
		public void onShowPress(MotionEvent e) {
			// TODO Auto-generated method stub

		}

		@Override
		public boolean onSingleTapUp(MotionEvent e) {
			// TODO Auto-generated method stub
			return false;
		}
	}

	//多点手势控制
	private class MultiGestureListener implements OnScaleGestureListener {

		@Override
		public boolean onScale(ScaleGestureDetector detector) {
			// TODO Auto-generated method stub
			return false;
		}

		@Override
		public boolean onScaleBegin(ScaleGestureDetector detector) {
			// TODO Auto-generated method stub
			// 返回true ,才能进入onscale()函数
			return true;
		}

		@Override
		public void onScaleEnd(ScaleGestureDetector detector) {
			// TODO Auto-generated method stub
			float oldDis = detector.getPreviousSpan();
			float curDis = detector.getCurrentSpan();
			if (oldDis - curDis > 50) {
				// 缩小
				changeLayout(0);
				Toast.makeText(VideoPlay.this, "缩小", Toast.LENGTH_LONG).show();
			} else if (oldDis - curDis < -50) {
				// 放大
				changeLayout(1);
				Toast.makeText(VideoPlay.this, "放大", Toast.LENGTH_LONG).show();
			}
		}

	}
}
------------视频布局activity_video(activity_main里面没写省略):
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent" >

    <io.vov.vitamio.widget.VideoView
        android:id="@+id/surface_view"
        android:layout_centerInParent="true"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content" />

    <FrameLayout
        android:id="@+id/operation_volume_brightness"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_centerInParent="true"
        android:background="#00000000"
        android:orientation="horizontal"
        android:padding="0dip"
        android:visibility="invisible" >

        <ImageView
            android:id="@+id/operation_bg"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_gravity="center"
            android:src="@drawable/video_volumn_bg" />

        <FrameLayout
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_gravity="bottom|center_horizontal"
            android:paddingBottom="25dip" >

            <ImageView
                android:id="@+id/operation_full"
                android:layout_width="94dip"
                android:layout_height="wrap_content"
                android:layout_gravity="left"
                android:src="@drawable/video_num_bg" />

            <ImageView
                android:id="@+id/operation_percent"
                android:layout_width="0dip"
                android:layout_height="wrap_content"
                android:layout_gravity="left"
                android:scaleType="matrix"
                android:src="@drawable/video_num_front" />
        </FrameLayout>
    </FrameLayout>

</RelativeLayout>
-------------Androidmanifest清单文件(4个注意点):
1.权限:
    <uses-sdk
        android:minSdkVersion="7"
        android:targetSdkVersion="23" />

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

2.注意初始化vitamio的InitActivity:
      <!-- Don't forgot InitActivity -->
        <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" />
3.添加intent隐式意图,对sd卡支持的文件格式添加本程序的打开方式:
     <activity android:name=".MainActivity">
            <intent-filter>
                <action android:name="android.intent.action.MAIN"/>

                <category android:name="android.intent.category.LAUNCHER"/>
            </intent-filter>
            <intent-filter>
                <action android:name="android.intent.action.VIEW"></action>
                <category android:name="android.intent.category.DEFAULT"></category>
                <data android:mimeType="video/*"/>
                <data android:mimeType="application/mp4"/>
                <data android:mimeType="*/rmvb"/>
                <data android:mimeType="*/avi"/>
                <data android:mimeType="*/mkv"/>
                <data android:mimeType="audio/x-pn-realaudio"/>
                <data android:mimeType="video/x-ms-asf"/>
                <data android:mimeType="video/quicktime"/>
                <data android:mimeType="application/mpeg*"/>
                <data android:mimeType="application/vnd.rn-realmedia*"/>
                <data android:mimeType="application/3gpp*"/>
                <data android:mimeType="application/vnd.3gp*"/>
                <data android:mimeType="application/vnd.dvb*"/>
                <data android:mimeType="application/vnd.dolby*"/>
                <data android:mimeType="application/octet-stream"/>
            </intent-filter>
        </activity>
4.添加视频播放控制的Activity:
        <activity
            android:name=".VideoPlay"
            android:screenOrientation="landscape" >
        </activity>

-------库和图片资源路径:
个人网盘链接:http://pan.baidu.com/s/1jHSoZSM 密码:03hm

视频项目完整代码或者编写出问题的可以给我评论留言,我后面会解答













Android本地文件点击视频播放器vitamio版

原文:http://blog.csdn.net/insist_hui/article/details/51923765

(0)
(0)
   
举报
评论 一句话评论(0
关于我们 - 联系我们 - 留言反馈 - 联系我们:wmxa8@hotmail.com
© 2014 bubuko.com 版权所有
打开技术之扣,分享程序人生!