在Android中提供了一个VideoView播放视频,用于播放视频文件,要想使用VideoView组件播放视频,首先需要在布局文件中创建该组件,然后在Activity中获取该组件,并用 setVideoPath() 方法或 setVideoURI() 方法加载要播放的视频,最后调用VideoView组件的 start() 方法来播放视频。
MediaContraller组件用于通过图形控制界面来控制视频的播放.
/**
* //初始化
* playVideo=(VideoView)findViewById(R.id.video_view);
* MediaController mc=new MediaController(this);// 媒体控制器
* // MediaController与VideoView关联
* mc.setAnchorView(playVideo);
* // VideoView与MediaController关联
* playVideo.setMediaController(mc);
* //调用播放
* String path=new File(Environment.getExternalStorageDirectory(),
* "bhhd.mp4").getAbsolutePath();
* System.out.println("path:"+path);
* playVideo.setVideoPath(path);
* playVideo.start();
*/
public class VideoViewActivity extends AppCompatActivity implements View.OnClickListener {
VideoView videoView;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_video_view);
videoView = (VideoView) findViewById(R.id.video_view);
//设置视频播放路径
videoView.setVideoPath("/mnt/sdcard/Movies/an_xiang.mp4");
//设置播放控制器
videoView.setMediaController(new MediaController(this));
findViewById(R.id.btn_play).setOnClickListener(this);
findViewById(R.id.btn_pause).setOnClickListener(this);
findViewById(R.id.btn_stop).setOnClickListener(this);
}
@Override
public void onClick(View v) {
switch (v.getId()) {
case R.id.btn_play:
videoView.start();
break;
case R.id.btn_pause:
videoView.pause();
break;
case R.id.btn_stop:
videoView.stopPlayback();
break;
}
}
}
结合 TextureView 定义视频播放器
需要监听 Surface 创建完毕时才可以播放
private void init() {
setSurfaceTextureListener(new SurfaceTextureListener() {
@Override
public void onSurfaceTextureAvailable(SurfaceTexture surface, int width, int height) {
mSurface = new Surface(surface);
start();
}
@Override
public void onSurfaceTextureSizeChanged(SurfaceTexture surface, int width, int height) {
}
@Override
public boolean onSurfaceTextureDestroyed(SurfaceTexture surface) {
stop();
return true;
}
@Override
public void onSurfaceTextureUpdated(SurfaceTexture surface) {
}
});
}
MediaPlayer 需要使用 setSurface(Surface) 方法来设置画面显示的位置 , 如果时 SurfaceView 需要用 setDisplay(SurfaceHolder)
private void initPlayer() {
if (null == mPlayer) {
mPlayer = new MediaPlayer();
//设置准备监听
mPlayer.setOnPreparedListener(onPreparedListener);
//设置错误监听
mPlayer.setOnErrorListener(onErrorListener);
//设置播放完毕监听
mPlayer.setOnCompletionListener(onCompletionListener);
mPlayer.setOnVideoSizeChangedListener(onVideoSizeChangedListener);
mPlayer.setAudioStreamType(AudioManager.STREAM_MUSIC);
//设置视频画面显示位置
mPlayer.setSurface(mSurface);
} else {
mPlayer.reset();
}
//1、让MediaPlayer进入idle状态
}
//开始解析文件
private void setDataAndPlay(String path) {
isStop = false;
//设置播放的数据源
try {
mPlayer.setDataSource(path);
//2、进入initialized状态
//准备
mPlayer.prepareAsync();
} catch (Exception e) {
isStop = true;
}
}
视频播放在准备完毕时可以获取视频宽高
int videoWidth = mp.getVideoWidth();
int videoHeight = mp.getVideoHeight();
测试代码Demo
View包下新建一view类
public class XVideoView extends TextureView {
private static final int MSG_UPDATE_POSITION = 1;
private MediaPlayer mPlayer;
//视频画面显示的载体
private Surface mSurface;
private int mVideoWidth;
private int mVideoHeight;
//更新的进度条
private SeekBar seekBar;
private boolean isStop = true;
private int playPos;
private Uri uri; // http: file:
public XVideoView(Context context) {
super(context);
init();
}
public XVideoView(Context context, AttributeSet attrs) {
super(context, attrs);
init();
}
private void init() {
setSurfaceTextureListener(new SurfaceTextureListener() {
@Override
public void onSurfaceTextureAvailable(SurfaceTexture surface, int width, int height) {
mSurface = new Surface(surface);
start();
}
@Override
public void onSurfaceTextureSizeChanged(SurfaceTexture surface, int width, int height) {
}
@Override
public boolean onSurfaceTextureDestroyed(SurfaceTexture surface) {
stop();
return true;
}
@Override
public void onSurfaceTextureUpdated(SurfaceTexture surface) {
}
});
}
private void initPlayer() {
if (null == mPlayer) {
mPlayer = new MediaPlayer();
//设置准备监听
mPlayer.setOnPreparedListener(onPreparedListener);
//设置错误监听
mPlayer.setOnErrorListener(onErrorListener);
//设置播放完毕监听
mPlayer.setOnCompletionListener(onCompletionListener);
mPlayer.setOnVideoSizeChangedListener(onVideoSizeChangedListener);
mPlayer.setAudioStreamType(AudioManager.STREAM_MUSIC);
//设置视频画面显示位置
mPlayer.setSurface(mSurface);
} else {
mPlayer.reset();
}
//1、让MediaPlayer进入idle状态
}
//开始解析文件
private void setDataAndPlay(String path) {
isStop = false;
//设置播放的数据源
try {
mPlayer.setDataSource(path);
//2、进入initialized状态
//准备
mPlayer.prepareAsync();
} catch (Exception e) {
isStop = true;
}
}
private MediaPlayer.OnPreparedListener onPreparedListener = new MediaPlayer.OnPreparedListener() {
@Override
public void onPrepared(MediaPlayer mp) {
isStop = false;
//3、进入onPrepared状态(准备完毕),可以去start、pause、seekTo、stop
//获取总时间
seekBar.setMax(100);
if (playPos > 0) {
mp.seekTo(playPos);
}
mp.start();
//更新播放时间
mHandler.sendEmptyMessageDelayed(MSG_UPDATE_POSITION, 200);
}
};
//(解码)错误监听
private MediaPlayer.OnErrorListener onErrorListener = new MediaPlayer.OnErrorListener() {
@Override
public boolean onError(MediaPlayer mp, int what, int extra) {
mHandler.removeMessages(MSG_UPDATE_POSITION);
playPos = mp.getCurrentPosition();
mp.stop();
mp.reset(); //进入idle状态
isStop = true;
return true;
}
};
//播放完毕监听
private MediaPlayer.OnCompletionListener onCompletionListener = new MediaPlayer.OnCompletionListener() {
@Override
public void onCompletion(MediaPlayer mp) {
mHandler.removeMessages(MSG_UPDATE_POSITION);
}
};
private MediaPlayer.OnVideoSizeChangedListener onVideoSizeChangedListener = new MediaPlayer.OnVideoSizeChangedListener() {
@Override
public void onVideoSizeChanged(MediaPlayer mp, int width, int height) {
mVideoWidth = mp.getVideoWidth();
mVideoHeight = mp.getVideoHeight();
if (mVideoWidth != 0 && mVideoHeight != 0) {
requestLayout();
}
}
};
private Handler mHandler = new Handler() {
@Override
public void handleMessage(Message msg) {
if (msg.what == MSG_UPDATE_POSITION) {
if (mPlayer != null) {
int pos = mPlayer.getCurrentPosition(); //获取当前的播放时间
int duration = mPlayer.getDuration();
int position = 100 * pos / duration;
seekBar.setProgress(position);
sendEmptyMessageDelayed(MSG_UPDATE_POSITION, 200);
}
}
}
};
public void start() {
if (mPlayer == null) {
initPlayer();
String sc = uri.getScheme();
if ("http".equalsIgnoreCase(sc) || "https".equalsIgnoreCase(sc)) {
new DownloadTack().execute(uri.toString(), "/mnt/sdcard/" + System.currentTimeMillis() + ".mp3");
}else{
setDataAndPlay(uri.toString());
}
} else {
if (!mPlayer.isPlaying()) {
mPlayer.start();
mHandler.sendEmptyMessageDelayed(MSG_UPDATE_POSITION, 200);
}
}
}
public void pause() {
if (null != mPlayer && mPlayer.isPlaying()) {
mHandler.removeMessages(MSG_UPDATE_POSITION);
mPlayer.pause();
}
}
public void stop() {
if (null != mPlayer) {
mHandler.removeMessages(MSG_UPDATE_POSITION);
mPlayer.stop();
mPlayer.release();
mPlayer = null;
seekBar.setProgress(0);
}
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
//Log.i("@@@@", "onMeasure(" + MeasureSpec.toString(widthMeasureSpec) + ", "
// + MeasureSpec.toString(heightMeasureSpec) + ")");
int width = getDefaultSize(mVideoWidth, widthMeasureSpec);
int height = getDefaultSize(mVideoHeight, heightMeasureSpec);
if (mVideoWidth > 0 && mVideoHeight > 0) {
int widthSpecMode = MeasureSpec.getMode(widthMeasureSpec);
int widthSpecSize = MeasureSpec.getSize(widthMeasureSpec);
int heightSpecMode = MeasureSpec.getMode(heightMeasureSpec);
int heightSpecSize = MeasureSpec.getSize(heightMeasureSpec);
if (widthSpecMode == MeasureSpec.EXACTLY && heightSpecMode == MeasureSpec.EXACTLY) {
// the size is fixed
width = widthSpecSize;
height = heightSpecSize;
// for compatibility, we adjust size based on aspect ratio
if (mVideoWidth * height < width * mVideoHeight) {
//Log.i("@@@", "image too wide, correcting");
width = height * mVideoWidth / mVideoHeight;
} else if (mVideoWidth * height > width * mVideoHeight) {
//Log.i("@@@", "image too tall, correcting");
height = width * mVideoHeight / mVideoWidth;
}
} else if (widthSpecMode == MeasureSpec.EXACTLY) {
// only the width is fixed, adjust the height to match aspect ratio if possible
width = widthSpecSize;
height = width * mVideoHeight / mVideoWidth;
if (heightSpecMode == MeasureSpec.AT_MOST && height > heightSpecSize) {
// couldn't match aspect ratio within the constraints
height = heightSpecSize;
}
} else if (heightSpecMode == MeasureSpec.EXACTLY) {
// only the height is fixed, adjust the width to match aspect ratio if possible
height = heightSpecSize;
width = height * mVideoWidth / mVideoHeight;
if (widthSpecMode == MeasureSpec.AT_MOST && width > widthSpecSize) {
// couldn't match aspect ratio within the constraints
width = widthSpecSize;
}
} else {
// neither the width nor the height are fixed, try to use actual video size
width = mVideoWidth;
height = mVideoHeight;
if (heightSpecMode == MeasureSpec.AT_MOST && height > heightSpecSize) {
// too tall, decrease both width and height
height = heightSpecSize;
width = height * mVideoWidth / mVideoHeight;
}
if (widthSpecMode == MeasureSpec.AT_MOST && width > widthSpecSize) {
// too wide, decrease both width and height
width = widthSpecSize;
height = width * mVideoHeight / mVideoWidth;
}
}
} else {
// no size yet, just adopt the given spec sizes
}
setMeasuredDimension(width, height);
}
public SeekBar getSeekBar() {
return seekBar;
}
public void setSeekBar(SeekBar seekBar) {
this.seekBar = seekBar;
seekBar.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() {
@Override
public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
}
@Override
public void onStartTrackingTouch(SeekBar seekBar) {
if (mPlayer != null && mPlayer.isPlaying()) {
mHandler.removeMessages(MSG_UPDATE_POSITION);
}
}
@Override
public void onStopTrackingTouch(SeekBar seekBar) {
if (mPlayer != null) {
int pos = seekBar.getProgress(); //获取拖动到的位置
//计算该进度对应的时间轴
int currentPos = pos * mPlayer.getDuration() / 100;
mPlayer.seekTo(currentPos); //设置播放位置
if (mPlayer.isPlaying()) {
mHandler.sendEmptyMessageDelayed(MSG_UPDATE_POSITION, 200);
}
}
}
});
}
class DownloadTack extends AsyncTask<String, Integer, Object> implements MediaDownloader.OnDownloadListener {
int lenght; //记录总大小
String savePath;
@Override
protected Object doInBackground(String... params) {
new MediaDownloader(this).download(params[0], params[1]);
return null;
}
@Override
public void onStart(int size, String path) {
lenght = size;
this.savePath = path;
}
@Override
public void onDownloading(int currentSize) {
//更新进度条
if (currentSize >= 1024 && isStop) {
//开始解析
setDataAndPlay(savePath);
}
int currentRate = 100 * currentSize / lenght;
publishProgress(currentRate);
}
@Override
protected void onProgressUpdate(Integer... values) {
seekBar.setSecondaryProgress(values[0]);
}
}
public Uri getUri() {
return uri;
}
public void setUri(Uri uri) {
this.uri = uri;
}
}
注册TextureViewPlayVideoActivity类
public class TextureViewPlayVideoActivity extends AppCompatActivity implements View.OnClickListener {
private XVideoView xVideoView;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_texture_view_play_video);
xVideoView = (XVideoView) findViewById(R.id.player_view);
SeekBar seekBar = (SeekBar) findViewById(R.id.seek_bar);
xVideoView.setSeekBar(seekBar);
findViewById(R.id.btn_play).setOnClickListener(this);
findViewById(R.id.btn_pause).setOnClickListener(this);
findViewById(R.id.btn_stop).setOnClickListener(this);
// xVideoView.setUri(Uri.parse("/mnt/sdcard/Movies/an_xiang.mp4"));
xVideoView.setUri(Uri.parse("http://192.168.18.251:8080/MediaServer/video/gee.mp4"));
}
@Override
public void onClick(View v) {
switch (v.getId()) {
case R.id.btn_play:
xVideoView.start();
break;
case R.id.btn_pause:
xVideoView.pause();
break;
case R.id.btn_stop:
xVideoView.stop();
break;
}
}
}
版权声明:本文为qq_35980005原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明。