现在视频格式有:AVI/VCD/SVCD/DVD/MPG/WMV/ASF/RM/RMVB/FLV/F4V/MOV/QT/MP4/MPEG4/3GP/3G2/MKV/TS/TP/MTS/M2TS/MOD/TOD/SDP/YUV等。
在Android中,一般有下面几种方式来实现视频的播放:
1、利用Intent调用系统自带的播放器或者安装的第三方播放器。指定Action为ACTION_VIEW,Data为Uri,Type为其MIME类型。
2、使用VideoView来播放。在布局文件中使用VideoView结合MediaController来实现对其控制。
3、使用MediaPlayer类和SurfaceView来实现,这种方式很灵活。
4、使用开源框架实现。
一、调用已有播放器
Uri uri=Uri.parse("***");
Intent intent=new Intent(Intent.ACTION_VIEW);
intent.setDataAndType(uri,"video/*");
startActivity(intent);
这种方式很简单只要设置好视频路径(可以是本地路径和网络路径),系统就会自动检索手机上已安装的视频播放器来播放。这种方式依赖于选择播放器的支持视频格式,基本会支持所有视频格式。
二、利用VideoView来播放视频(只支持mp4、avi、3gp格式的视频,支持格式单一)
ViewView是系统封装好的SurfaceView,所以特点就是调用简单,但是定制困难,而且同SurfaceView一样,会遇到很多异常情况,推荐一篇文章就是在实际项目中用的VideoView里面记录了很多问题以及解决方法,文章推荐。再推荐一个完整的视频项目开发文章文章推荐
简单的VideoView使用
/**
*初始化videoview播放
*/
public void initVideoView(){
//初始化进度条
progressBar= (ProgressBar) findViewById(R.id.progressBar);
//初始化VideoView
videoView= (VideoView) findViewById(R.id.videoView);
//初始化videoview控制条
mediaController=new MediaController(this);
//设置videoview的控制条
videoView.setMediaController(mediaController);
//设置显示控制条
mediaController.show(0);
//设置播放完成以后监听
videoView.setOnCompletionListener(this);
//设置发生错误监听,如果不设置videoview会向用户提示发生错误
videoView.setOnErrorListener(this);
//设置在视频文件在加载完毕以后的回调函数
videoView.setOnPreparedListener(this);
//设置videoView的点击监听
videoView.setOnTouchListener(this);
//设置网络视频路径
Uri uri=Uri.parse("***");
videoView.setVideoURI(uri);
//设置为全屏模式播放
setVideoViewLayoutParams(1);
}
三、MediaPlayer+surfaceView是其他方法的基础,其他方法都是对其进行封装的
我们都知道MediaPlayer是媒体播放器,可以播放音频,视频其实就是给音频配上影像,而SurfaceView就是给音频配上影像的工具,我们只需要把SurfaceView与MediaPlayer关联起来就行了。
SurfaceHolder holder = SurfaceView.getHolder();
...
MediaPlayer.setDisplay(holder);//将影像播放控件与媒体播放控件关联起来
简单demo实现
sfv = (SurfaceView) findViewById(R.id.sfv);
sb = (SeekBar) findViewById(R.id.sb);
Play = (Button) findViewById(R.id.play);
et = (EditText) findViewById(R.id.et);
Play.setEnabled(false);
holder = sfv.getHolder();
holder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
sb.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() {
@Override
public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
}
@Override
public void onStartTrackingTouch(SeekBar seekBar) {
}
@Override
public void onStopTrackingTouch(SeekBar seekBar) {
//当进度条停止拖动的时候,把媒体播放器的进度跳转到进度条对应的进度
if (player != null) {
player.seekTo(seekBar.getProgress());
}
}
});
holder.addCallback(new SurfaceHolder.Callback() {
@Override
public void surfaceCreated(SurfaceHolder holder) {
//为了避免图像控件还没有创建成功,用户就开始播放视频,造成程序异常,所以在创建成功后才使播放按钮可点击
Log.d("nantang","surfaceCreated");
Play.setEnabled(true);
}
@Override
public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
Log.d("nantang","surfaceChanged");
}
@Override
public void surfaceDestroyed(SurfaceHolder holder) {
//当程序没有退出,但不在前台运行时,因为surfaceview很耗费空间,所以会自动销毁,
// 这样就会出现当你再次点击进程序的时候点击播放按钮,声音继续播放,却没有图像
//为了避免这种不友好的问题,简单的解决方式就是只要surfaceview销毁,我就把媒体播放器等
//都销毁掉,这样每次进来都会重新播放,当然更好的做法是在这里再记录一下当前的播放位置,
//每次点击进来的时候把位置赋给媒体播放器,很简单加个全局变量就行了。
Log.d("nantang","surfaceDestroyed");
if (player != null) {
position = player.getCurrentPosition();
stop();
}
}
});
}
private void play() {
Play.setEnabled(false);//在播放时不允许再点击播放按钮
if (isPause) {//如果是暂停状态下播放,直接start
isPause = false;
player.start();
return;
}
path = Environment.getExternalStorageDirectory().getPath()+"/";
path = path + et.getText().toString();//sdcard的路径加上文件名称是文件全路径
File file = new File(path);
if (!file.exists()) {//判断需要播放的文件路径是否存在,不存在退出播放流程
Toast.makeText(this,"文件路径不存在",Toast.LENGTH_LONG).show();
return;
}
try {
player = new MediaPlayer();
player.setDataSource(path);
player.setDisplay(holder);//将影像播放控件与媒体播放控件关联起来
player.setOnCompletionListener(new MediaPlayer.OnCompletionListener() {
@Override
public void onCompletion(MediaPlayer mp) {//视频播放完成后,释放资源
Play.setEnabled(true);
stop();
}
});
/**
*prepare方法是将资源同步缓存到内存中,一般加载本地较小的资源可以用这个,
*如果是较大的资源或者网络资源建议使用prepareAsync方法,异步加载.
*但如果想让资源启动,即start()起来,因为在异步中,如果不设置监听直接start的话,
*是拿不到这个资源,如果让线程睡眠一段时间,则可以取得资源,因为这个时候,
*异步线程已经取得资源,但不可能使用线程睡眠的方式来获取资源啊.
*所以就需要设置监听事件setOnPreparedListener();
*来通知MediaPlayer资源已经获取到了,然后实现onPrepared(MediaPlayer mp)方法.
*在里面启动MediaPlayer
*/
player.setOnPreparedListener(new MediaPlayer.OnPreparedListener() {
@Override
public void onPrepared(MediaPlayer mp) {
//媒体播放器就绪后,设置进度条总长度,开启计时器不断更新进度条,播放视频
Log.d("nantang","onPrepared");
sb.setMax(player.getDuration());
timer = new Timer();
task = new TimerTask() {
@Override
public void run() {
if (player != null) {
int time = player.getCurrentPosition();
sb.setProgress(time);
}
}
};
timer.schedule(task,0,500);
sb.setProgress(position);
player.seekTo(position);
player.start();
}
});
player.prepareAsync();
} catch (IOException e) {
e.printStackTrace();
}
}
四、开源框架
1、Vitamio
2、VLC
公司机器人上的播放器就是基于VLC,效果挺好的,不过没具体研究过,后期研究研究。
网友评论