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

本博客用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

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

时间: 2024-10-06 04:42:39

Android本地文件点击视频播放器vitamio版的相关文章

Android本地视频播放器mediaplay版

本文为自定义的视频播放器,可进行屏幕切换(由于换屏时大小变化,电脑截图就分开截图了),效果如下图: --------------播放视频概括: SurfaceView+MediaPlayer以及 VideoView 2种方式 SurfaceVIew中有个SurfaceHolder,通过surfaceView.getHolder( )方法获取,如果需要兼容2.3系统,还要再加上setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);否则只有声音没有图像.有

Android进阶:十一、视频播放器初体验

上一篇文章我们主要讲了视频播放器开发之前需要准备的一直个知识,TextureView,用于对图像流的处理.这篇文章开始构建一个基础的视频播放器. 一.准备工作 在之前的文章已经说过了,播放器也是一个view,我们要在这个view上播放视频流.所以我们要自定义一个简单的viewgroup,比如继承FrameLayout.还出就是布局简单,其他控件可以往上面添加.大家见过的视频播放器的控制器都是放在视频的上方的.这样就是用FrameLayout布局是最好的. class SmallVideoPlay

最简单的基于DirectShow的示例:视频播放器自定义版

本文记录一个简单的基于DirectShow的自定义的视频播放器.这里所说的"自定义播放器",实际上指的是自己在Filter Graph中手动逐个添加Filter,并且连接这些Filter的后运行的播放器.这么做相对于使用RenderFile()这种"智能"创建Filter Graph的方法来说要复杂不少,但是可以让我们更加了解DirectShow的体系. 流程图 最简单的基于DirectShow的自定义的视频播放器的流程如下图所示. 该流程图中包含如下变量: IGr

在网站中嵌入VideoJs视频播放器

一个博客难免需要引用视频来说明内容,但想要自己来实现一个视频播放器是不是一时半会就能完成的,更重要的是这需要对视频播放技术有一定的了解.于是自然而然的有人会想到开源项目. html5已经原生支持视频元素 而我正在使用地便是video.js.它能够控制基本的播放器样式,支持mp4.webm.ogv视频格式,也能够插入字幕,基本上能够满足常用需求. video.js也使用了html5的特性,如果浏览器不支持html5的话,想要播放视频还得用flash,虽然flash由于资源的消耗广为诟病,但是由于国

转:最简单的基于 DirectShow 的视频播放器

50行代码实现的一个最简单的基于 DirectShow 的视频播放器 本文介绍一个最简单的基于 DirectShow 的视频播放器.该播放器对于初学者来说是十分有用的,它包含了使用 DirectShow 播放视频所有必备的函数. 直接贴上代码,具体代码的含义都写在注释中了: /* 雷霄骅 * 中国传媒大学/数字电视技术 * [email protected] * */ // aviplayer.cpp : 定义控制台应用程序的入口点. #include "stdafx.h" #incl

Android Studio上手,基于VideoView的本地文件及流媒体播放器

既然是第一个Android程序,少不了要Hello World. 1. 新建安卓工程 2. 输入工程名称 3. 选择平台版本 4. 选择一个空的Activity 5. 定制自己的Activity 点击Finish后,便生成了可以直接运行的Hello World程序.下面开始讨论怎样使这个只能打印Hello World的程序能够播放本地和网络视频. 此处附上功能目录结构: 6. 布局文件 首先需要重新布局.设计器的设计结果是保存在"activity_video_view_demo.xml"

Android--使用开源vitamio做万能视频播放器

Vitamio 是什么? Vitamio 是一款 Android 与 iOS 平台上的全能多媒体开发框架,全面支持硬件解码与 GPU 渲染.Vitamio 凭借其简洁易用的 API 接口赢得了全球众多开发者的青睐.到目前,全球已经有超过 一万 种应用在使用 Vitamio,覆盖用户超过 5亿 . Vitamio 能够流畅播放720P甚至1080P高清MKV,FLV,MP4,MOV,TS,RMVB等常见格式的视频,还可以在 Android 与 iOS 上跨平台支持 MMS, RTSP, RTMP,

22_Android中的本地音乐播放器和网络音乐播放器的编写,本地视频播放器和网络视频播放器

?? 1 编写以下案例: 当点击了"播放"之后,在手机上的/mnt/sdcard2/natural.mp3就会播放. 2 编写布局文件activity_main.xml <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_wi

Android(java)学习笔记243:多媒体之视频播放器

1.这里我们还是利用案例演示视频播放器的使用: (1)首先,我们看看布局文件activity_main.xml,如下: 1 <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" 2 xmlns:tools="http://schemas.android.com/tools" 3 android:layout_width="match_parent"