工作以来,一直偷懒,没有好好整理过自己的知识,从今天打算下定决心,开始整理笔记,记录自己的技术点滴,写给自己。不扯淡,直接进入正题。
Android多媒体包括音频,视频,图片,流媒体等,这里我只说视频的处理,视频分为本地视频与网络视频,这里先说本地视频,这个比较简单。一般有两种方式:
1、使用MediaPlayer来播放视频,当然它也可以播放音频;其底层是基于OpenCore(PacketVideo)的库实现的,为了构建一个MediaPlayer程序,上层还包含了进程间通讯等内容,
这种进程间通讯的基础是Android基本库中的Binder机制(这里不做过多叙述);初始化操作reset(),调用release()方法,让音频或者视频结束,设置数据源setDataSource(),同时设置error监听器,如果资源有问题,会回调onError()方法结束;然后准备资源,如果是小资源是本地且占用空间比较小,就用prepare()方法,如果是网络上的资源或者大的资源,就用prepareAsync()方法,异步准备完成之后,然后去回调OnPrepareListener接口的onPrepared()方法,音频或者视频资源准备完成Prepared;这时,可以直接调用start()方法,开始播放,started与paused暂停可以相互转换,同时可以调用seekTo方法;当调用stop方法后,再起启动的时候,需要先prepare在start这里要注意,当播放完成之后,会调用playbackComplete()。
播放视频的步骤: ①创建MediaPlayer对象,并让他加载制定的数据源(视频文件)
②在界面布局文件中定义SurfaceView组件,或者代码创建,并为SurfaceView的SurfaceHodler添加Callback监听器。
③调用MediaPlayer对象的setDisplay(holder)方法,设置视频显示的位置
④设置音频流对象、数据源、异步准备,各种监听,错误完成接口,走上述声明周期方法
具体代码如下:
mSurfaceView = (SurfaceView) findViewById(R.id.surfaceview);
mSurHolder = mSurfaceView.getHolder();
mSurfaceView.getHolder().addCallback(new Callback() {
// 当前的surfaceView销毁的时候调用
@Override
public void surfaceDestroyed(SurfaceHolder holder) {
Log.i("TAG", "surfaceDestroyed");
// 在SurfaceView被销毁之前保存当前的视频播放位置
if (mMediaPlayer != null) {
mCurrentPosition = mMediaPlayer.getCurrentPosition();
mMediaPlayer.stop();
mMediaPlayer.release();
}
}
// 当前surfaceView创建的时候调用
@Override
public void surfaceCreated(SurfaceHolder holder) {
try {
if (mCurrentPosition > 0) {
mMediaPlayer = new MediaPlayer();
// 设置音频流类型
mMediaPlayer
.setAudioStreamType(AudioManager.STREAM_MUSIC);
// 设置视频显示位置
mMediaPlayer.setDisplay(mSurHolder);
// 设置播放的资源路径
mMediaPlayer.setDataSource(mp4Path);
// 准备播放
// mMediaPlayer.prepare();
mMediaPlayer.prepareAsync();
// 准备播放的监听器
mMediaPlayer
.setOnPreparedListener(new OnPreparedListener() {
@Override
public void onPrepared(MediaPlayer mp) {
// 开始播放
mMediaPlayer.start();
mMediaPlayer.seekTo(mCurrentPosition);
}
});
// 设置播放按钮不能点击
mStart.setEnabled(false);
// 播放完成的状态
mMediaPlayer
.setOnCompletionListener(new OnCompletionListener() {
@Override
public void onCompletion(MediaPlayer mp) {
mStart.setEnabled(true);
}
});
}
} catch (IOException e) {
e.printStackTrace();
}
}
// 当前SurfaceView被改变的时候调用
@Override
public void surfaceChanged(SurfaceHolder holder, int format,
int width, int height) {
Log.i("TAG", "surfaceChanged");
}
});
播放的代码
private void play() {
try {
mMediaPlayer = new MediaPlayer();
// 设置音频流类型
mMediaPlayer.setAudioStreamType(AudioManager.STREAM_MUSIC);
// 设置视频显示位置
mMediaPlayer.setDisplay(mSurHolder);
// 设置播放的资源路径
mMediaPlayer.setDataSource(mp4Path);
// 准备播放
// mMediaPlayer.prepare();
mMediaPlayer.prepareAsync();
// 准备播放的监听器
mMediaPlayer.setOnPreparedListener(new OnPreparedListener() {
@Override
public void onPrepared(MediaPlayer mp) {
// 开始播放
mMediaPlayer.start();
}
});
// 设置播放按钮不能点击
mStart.setEnabled(false);
// 播放完成的状态
mMediaPlayer.setOnCompletionListener(new OnCompletionListener() {
@Override
public void onCompletion(MediaPlayer mp) {
mStart.setEnabled(true);
}
});
// 播放的过程中出现问题 设置播放按钮能点击
mMediaPlayer.setOnErrorListener(new OnErrorListener() {
@Override
public boolean onError(MediaPlayer mp, int what, int extra) {
int mediaErrorServerDied = MediaPlayer.MEDIA_ERROR_SERVER_DIED;
mStart.setEnabled(true);
return false;
}
});
} catch (IOException e) {
e.printStackTrace();
}
}
2、使用VideoView来播放视频,首先它继承自SurfaceView,整合了MediaPlayer,将二者进行了封装,可以使用setVideoPath(String path)制定本地资源,setVideoURI(Uri uri):加载uri对应的视频;对视频控制的时候可以使用setMediaController(new MediaController(this)),使用起来更加方便,不用自己控制播放与暂停,并且实现了接口setOnPreparedListener(),当准备好后可以播放视频
具体的使用代码如下:
Uri uri = Uri.parse("http://211.149.213.143/video_temp/fb586b2f216244f0bf4597242e8ca350.mp4");
VideoView videoView = (VideoView)this.findViewById(R.id.video_view);
videoView.setMediaController(new MediaController(this));
videoView.setVideoURI(uri);
videoView.start();
videoView.requestFocus();
接下来的文章会介绍一下http渐进下载协议与rtsp/rtp实时流媒体协议,同时在收一下SurfaceView与普通View的不同