使用VideoView实现简单视频播放器
转载请注明出处:http://blog.csdn.net/hejjunlin/article/details/39471397
VideoView内部封装好了Mediaplayer.Android框架提供了VideoView类来封装MediaPalyer,这个VideoView类非常好用。Android自带的程序Gallery也是用VideoView实现的。相比之下,我们使用更方便 ,实现MediaPlayer.OnCompletionListener接口,将会在Video播完的时候得到通知,本例只是简单的结束程序如下:
另附我的一个还未成熟的播放器,下载地址:http://www.eoemarket.com/soft/370334.html,正在完善中
import android.app.Activity;
import android.content.Context;
import android.content.Intent;
import android.content.pm.ActivityInfo;
import android.content.res.Configuration;
import android.media.AudioManager;
import android.net.Uri;
import android.os.Bundle;
import android.os.Environment;
import android.os.Handler;
import android.os.Message;
import android.text.TextUtils;
import android.view.Display;
import android.view.GestureDetector.SimpleOnGestureListener;
import android.view.GestureDetector;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewGroup;
import android.view.WindowManager;
import android.widget.ImageView;
public class VideoPlayerActivity extends Activity implements OnCompletionListener {
private String mPath;
private String mTitle;
private VideoView mVideoView;
private View mVolumeBrightnessLayout;
private ImageView mOperationBg;
private ImageView mOperationPercent;
private AudioManager mAudioManager;
/** 最大声音 */
private int mMaxVolume;
/** 当前声音 */
private int mVolume = -1;
/** 当前亮度 */
private float mBrightness = -1f;
/** 当前缩放模式 */
private int mLayout = VideoView.VIDEO_LAYOUT_ZOOM;
private GestureDetector mGestureDetector;
private MediaController mMediaController;
@Override
public void onCreate(Bundle icicle) {
super.onCreate(icicle);
Intent intent = getIntent();
mPath = intent.getStringExtra("path");
mTitle = intent.getStringExtra("title");
if (TextUtils.isEmpty(mPath))
mPath = Environment.getExternalStorageDirectory() + "/video/你太猖狂.flv";
else if (intent.getData() != null)
mPath = intent.getData().toString();
setContentView(R.layout.videoview);
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);
mAudioManager = (AudioManager) getSystemService(Context.AUDIO_SERVICE);
mMaxVolume = mAudioManager.getStreamMaxVolume(AudioManager.STREAM_MUSIC);
if (mPath.startsWith("http:"))
mVideoView.setVideoURI(Uri.parse(mPath));
else
mVideoView.setVideoPath(mPath);
//
mVideoView.setOnCompletionListener(this);
mMediaController = new MediaController(this);
//设置显示名称
mMediaController.setFileName(mTitle);
mVideoView.setMediaController(mMediaController);
mVideoView.requestFocus();
mGestureDetector = new GestureDetector(this, new MyGestureListener());
setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);
}
@Override
protected void onPause() {
super.onPause();
if (mVideoView != null)
mVideoView.pause();
}
@Override
protected void onResume() {
super.onResume();
if (mVideoView != null)
mVideoView.resume();
}
@Override
protected void onDestroy() {
super.onDestroy();
if (mVideoView != null)
mVideoView.stopPlayback();
}
@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;
// 隐藏
mDismissHandler.removeMessages(0);
mDismissHandler.sendEmptyMessageDelayed(0, 500);
}
private class MyGestureListener extends SimpleOnGestureListener {
/** 双击 */
@Override
public boolean onDoubleTap(MotionEvent e) {
if (mLayout == VideoView.VIDEO_LAYOUT_ZOOM)
mLayout = VideoView.VIDEO_LAYOUT_ORIGIN;
else
mLayout++;
if (mVideoView != null)
mVideoView.setVideoLayout(mLayout, 0);
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();
Display disp = getWindowManager().getDefaultDisplay();
int windowWidth = disp.getWidth();
int windowHeight = disp.getHeight();
if (mOldX > windowWidth * 4.0 / 5)// 右边滑动
onVolumeSlide((mOldY - y) / windowHeight);
else if (mOldX < windowWidth / 5.0)// 左边滑动
onBrightnessSlide((mOldY - y) / windowHeight);
return super.onScroll(e1, e2, distanceX, distanceY);
}
}
/** 定时隐藏 */
private Handler mDismissHandler = new Handler() {
@Override
public void handleMessage(Message msg) {
mVolumeBrightnessLayout.setVisibility(View.GONE);
}
};
/**
* 滑动改变声音大小
*
* @param percent
*/
private void onVolumeSlide(float percent) {
if (mVolume == -1) {
mVolume = mAudioManager.getStreamVolume(AudioManager.STREAM_MUSIC);
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;
// 变更声音
mAudioManager.setStreamVolume(AudioManager.STREAM_MUSIC, index, 0);
// 变更进度条
ViewGroup.LayoutParams lp = mOperationPercent.getLayoutParams();
lp.width = findViewById(R.id.operation_full).getLayoutParams().width * index / mMaxVolume;
mOperationPercent.setLayoutParams(lp);
}
/**
* 滑动改变亮度
*
* @param percent
*/
private void onBrightnessSlide(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);
}
@Override
public void onConfigurationChanged(Configuration newConfig) {
if (mVideoView != null)
mVideoView.setVideoLayout(mLayout, 0);
super.onConfigurationChanged(newConfig);
}
@Override
public void onCompletion(MediaPlayer player) {
finish();
}
}
videoView 是android 系统提供的一个媒体播放显示和控制的控件。其结构层次如下:
原型:VideoView extends SurfaceView implements MediaController.MediaPlayerControl
类结构:
java.lang.Object
↳ android.view.View
↳ android.view.SurfaceView
↳ android.widget.VideoView
通过VideoView 的原型可知:如果构建更为复杂和有特色个性的视频View,需要继承SurfaceView 和实现MediaPlayerControl接口。其中SurfaceView 为显示提供支持,MediaPlayerControl则为媒体控制提供了支持。
核心播放类:
import android.app.Activity;
import android.os.Bundle;
import android.os.Environment;
import android.util.Log;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
public class PlayerActivity extends Activity implements OnBufferingUpdateListener, OnCompletionListener, OnPreparedListener, OnVideoSizeChangedListener, SurfaceHolder.Callback {
private static final String TAG = "MediaPlayerDemo";
private int mVideoWidth;
private int mVideoHeight;
private MediaPlayer mMediaPlayer;
private SurfaceView mPreview;
private SurfaceHolder holder;
private String path = Environment.getExternalStorageDirectory() + "/Moon.mp4";
private boolean mIsVideoSizeKnown = false;
private boolean mIsVideoReadyToBePlayed = false;
@Override
public void onCreate(Bundle icicle) {
super.onCreate(icicle);
setContentView(R.layout.mediaplayer);
mPreview = (SurfaceView) findViewById(R.id.surface);
holder = mPreview.getHolder();
holder.addCallback(this);
}
private void playVideo() {
doCleanUp();
try {
mMediaPlayer = new MediaPlayer(this);
mMediaPlayer.setDataSource(path);
mMediaPlayer.setDisplay(holder);
mMediaPlayer.prepareAsync();
mMediaPlayer.setScreenOnWhilePlaying(true);
mMediaPlayer.setOnBufferingUpdateListener(this);
mMediaPlayer.setOnCompletionListener(this);
mMediaPlayer.setOnPreparedListener(this);
mMediaPlayer.setOnVideoSizeChangedListener(this);
} catch (Exception e) {
Log.e(TAG, "error: " + e.getMessage(), e);
}
}
@Override
public void onBufferingUpdate(MediaPlayer arg0, int percent) {
Log.d(TAG, "onBufferingUpdate percent:" + percent);
}
@Override
public void onCompletion(MediaPlayer arg0) {
Log.d(TAG, "onCompletion called");
mMediaPlayer.release();
}
@Override
public void onVideoSizeChanged(MediaPlayer mp, int width, int height) {
Log.v(TAG, "onVideoSizeChanged called");
if (width == 0 || height == 0) {
Log.e(TAG, "invalid video width(" + width + ") or height(" + height + ")");
return;
}
mIsVideoSizeKnown = true;
mVideoWidth = width;
mVideoHeight = height;
if (mIsVideoReadyToBePlayed && mIsVideoSizeKnown) {
startVideoPlayback();
}
}
@Override
public void onPrepared(MediaPlayer mediaplayer) {
Log.d(TAG, "onPrepared called");
mIsVideoReadyToBePlayed = true;
if (mIsVideoReadyToBePlayed && mIsVideoSizeKnown) {
startVideoPlayback();
}
}
@Override
public void surfaceChanged(SurfaceHolder surfaceholder, int i, int j, int k) {
Log.d(TAG, "surfaceChanged called" + i + " " + j + " " + k);
}
@Override
public void surfaceDestroyed(SurfaceHolder surfaceholder) {
Log.d(TAG, "surfaceDestroyed called");
}
@Override
public void surfaceCreated(SurfaceHolder holder) {
Log.d(TAG, "surfaceCreated called");
playVideo();
}
@Override
protected void onPause() {
super.onPause();
releaseMediaPlayer();
doCleanUp();
}
@Override
protected void onDestroy() {
super.onDestroy();
releaseMediaPlayer();
doCleanUp();
}
private void releaseMediaPlayer() {
if (mMediaPlayer != null) {
mMediaPlayer.release();
mMediaPlayer = null;
}
}
private void doCleanUp() {
mVideoWidth = 0;
mVideoHeight = 0;
mIsVideoReadyToBePlayed = false;
mIsVideoSizeKnown = false;
}
private void startVideoPlayback() {
Log.v(TAG, "startVideoPlayback");
holder.setFixedSize(mVideoWidth, mVideoHeight);
mMediaPlayer.start();
}
}
第一时间获得博客更新提醒,以及更多android干货,源码分析,欢迎关注我的微信公众号,扫一扫下方二维码,即可关注。
使用VideoView实现简单视频播放器的更多相关文章
- Opencv 简单视频播放器
// C++ header and namespace #include <iostream> #include <string> #include <cstdlib&g ...
- QT-简易视频播放器
一直没找到理由去学一下QT,由于工作原因之后的工作内容会用到QT,于是这两天摸索了下:早上临时决定先做个视频播放器玩一下,于是先用qml发现不会用,无果,于是放弃了使用qml,等之后系统的看一下Jav ...
- Android 视频播放器 (一):使用VideoView播放视频
一.简介 作为Android开发,我们不可避免的会接触到视频播放,VideoView做为最简单的播放器,我们是不应该不会的. 下面简单介绍一下VideoView: VideoView是使用MediaP ...
- 安卓视频播放器(VideoView)
VideoView是安卓自带的视频播放器类,该类集成有显示和控制两大部分,在布局文件中添加VideoView然后在java文件中简单的调用控制命令,即可实现本地或者网络视频的播放.本章实现视频的居中播 ...
- 转:最简单的基于 DirectShow 的视频播放器
50行代码实现的一个最简单的基于 DirectShow 的视频播放器 本文介绍一个最简单的基于 DirectShow 的视频播放器.该播放器对于初学者来说是十分有用的,它包含了使用 DirectSho ...
- 【转】100行代码实现最简单的基于FFMPEG+SDL的视频播放器
FFMPEG工程浩大,可以参考的书籍又不是很多,因此很多刚学习FFMPEG的人常常感觉到无从下手.我刚接触FFMPEG的时候也感觉不知从何学起. 因此我把自己做项目过程中实现的一个非常简单的视频播放器 ...
- 最简单的基于FFMPEG+SDL的视频播放器 ver2 (採用SDL2.0)
===================================================== 最简单的基于FFmpeg的视频播放器系列文章列表: 100行代码实现最简单的基于FFMPEG ...
- 最简单的基于DirectShow的示例:视频播放器自定义版
===================================================== 最简单的基于DirectShow的示例文章列表: 最简单的基于DirectShow的示例:视 ...
- 最简单的基于DirectShow的示例:视频播放器图形界面版
===================================================== 最简单的基于DirectShow的示例文章列表: 最简单的基于DirectShow的示例:视 ...
随机推荐
- SQL之排序
1.按多个列排序 经常需要按不止一个列进行数据排序.例如,如果要显示雇员名单,可能希望按姓和名排序(首先按姓排序,然后在每个姓中再按名排序).如果多个雇员有相同的姓,这样做很有用. 要按多个列排序,简 ...
- 微信小程序适配iphonex
// 在app.js中判断是否是哪种设备 globalData: { isIphoneX: false, userInfo: null }, onShow:function(){ let that ...
- jquery easyui datagrid 排序列
点击排序列,将获取参数有:page=1&rows=10&sort=UserName&order=desc c#后台获取sort跟order参数 string sortColum ...
- 网络协议 finally{ return问题 注入问题 jdbc注册驱动问题 PreparedStatement 连接池目的 1.2.1DBCP连接池 C3P0连接池 MYSQL两种方式进行实物管理 JDBC事务 DBUtils事务 ThreadLocal 事务特性 并发访问 隔离级别
1.1.1 API详解:注册驱动 DriverManager.registerDriver(new com.mysql.jdbc.Driver());不建议使用 原因有2个: >导致驱动被注册2 ...
- scan函数用法详解
scan函数: scan(s,n,"char")表示从字串string中以char为分隔符提取第n个字串 功能(function):从字符表达式s中搜取给定的n个单词语法(synt ...
- lucene全文检索基础
全文检索是一种将文件中所有文本与检索项匹配的文字资料检索方法.比如用户在n个小说文档中检索某个关键词,那么所有包含该关键词的文档都返回给用户.那么应该从哪里入手去实现一个全文检索系统?相信大家都听说过 ...
- FindBugs入门简介(eclipse安装使用实例)
前言:一般公司都会有一些开发规范,但是事实上,简单看那么一两遍并不能养成习惯,或者将这些规范记住.特别的,对于一些新手,写的代码往往会很糟糕.回头看看你一两年前写的代码就会知道,所谓的"糟糕 ...
- Android 5.0新控件——FloatingActionButton(悬浮按钮)
Android 5.0新控件--FloatingActionButton(悬浮按钮) FloatingActionButton是5.0以后的新控件,一个悬浮按钮,之所以叫做悬浮按钮,主要是因为自带阴影 ...
- Swift中String和NSString的一个不同之处
我们知道在Swift中String和NSString是可以互相转换使用的-额-应该是在绝大数情况下可以互相转换使用.在某些情况下可能还有一丝丝略微的差别:比如在涉及到处理字符串中字符索引的时候. 我们 ...
- ubuntu日志文件管理
众所周知,ubuntu的日志文件会越来越大,需要定期管理 logrotate是个十分有用的工具,它可以自动对日志进行截断(或轮循).压缩以及删除旧的日志文件.例如,你可以设置logrotate,让/v ...