MediaPlayer主要是用来播放音频的,因此它没有提供图像输出界面,此时就需要借助于SurfaceView来显示MediaPlayer播放时候的图像输出。
有几点要注意的:
1、MediaPlayer管理播放的,所以状态问题一定不能忽略的。
2、SurfaceHolder.setType(int)方法虽然被标记为deprecate的,但是最好还是对SurfaceView进行这样设置this.surfaceView.getHolder().setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
3、最好保证mediaPlayer.start()之后,在进行mediaPlayer.setDisplay()的设置,不过一般问题不大。
4、有时候会遇到只有声音没有图像的情况,那是因为surfaceview的创建优先级并不高,因此在mediaPlayer开始之后,surfaceView还没有创建出来,因此会出现有声音没图像的问题
一般有两种实现方法:
一是在通过holder增加callback,监听surfaceCreate事件,在监听到之后再开始mediaPlayer的相关操作,具体可以看videoView的实现方法
二是通过按钮来实现mediaPlayer,这样也可以保证再用户按到按钮之前,surfaceView已经被创建出来了。
下面是封装的操作播放视频的代码,因为需要,加了一些判断,不过基本的封装都有。
public class OperateMedia implements OnBufferingUpdateListener, OnCompletionListener, OnErrorListener { private int position = 0;// 保存播放的的位置 private SurfaceView surfaceView;// surfaceVie对象 private Context context;// 上下文对象 private MediaPlayer mediaPlayer;// mediaplayer对象 private int currentPlay = 0;// 保存当前正在播放的视频 0表示还没有记录 private boolean justBack = false;// 是否刚才另外一个界面跳回,fasle 表示不是 public OperateMedia(Context context, MediaPlayer mediaPlayer, SurfaceView surfaceView) { // TODO Auto-generated constructor stub this.context = context; this.mediaPlayer = mediaPlayer; this.surfaceView = surfaceView; // mediaPlayer的设置 this.mediaPlayer.setAudioStreamType(AudioManager.STREAM_MUSIC); this.mediaPlayer.setOnBufferingUpdateListener(this); this.mediaPlayer.setOnCompletionListener(this); // surfaceView的设置 this.surfaceView.getHolder().setKeepScreenOn(true); this.surfaceView.getHolder().setType( SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS); this.surfaceView.getHolder().addCallback(new SurfaceCallback()); // surfaceView的回调 } // 设置播放不同的视频 public void loadSrc(int num) { // 如果在次播放的是不同的视频,那么就将position初始化,并且reset,重新设置视频源 if (num != currentPlay) { position = 0; try { currentPlay = num; mediaPlayer.reset(); AssetFileDescriptor fd = null; switch (num) { case 0: fd = context.getAssets().openFd("a.mp4"); break; case 1: fd = context.getAssets().openFd("b.mp4"); break; case 2: fd = context.getAssets().openFd("c.mp4"); break; case 3: fd = context.getAssets().openFd("d.mp4"); break; } mediaPlayer.setDataSource(fd.getFileDescriptor(), fd.getStartOffset(), fd.getLength()); play(); } catch (IllegalArgumentException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (IllegalStateException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } return;// 中断当前程序 } // 如果点击的是同一个视频。那么就不用reset了 if (num == currentPlay) { if (justBack) { play(); return; } else {//如果不是从另一个activity切换回来,那么,就直接设置到0,开始播放 mediaPlayer.seekTo(0); mediaPlayer.start(); mediaPlayer.setDisplay(surfaceView.getHolder());// 设置屏幕 } } } // 播放视频 public void play() { mediaPlayer.prepareAsync(); mediaPlayer.setOnPreparedListener(new OnPreparedListener() { public void onPrepared(MediaPlayer mp) { if (position > 0) { mediaPlayer.seekTo(position); if (justBack) { justBack = false; position = 0; } } mediaPlayer.start(); } }); mediaPlayer.setDisplay(surfaceView.getHolder());// 设置屏幕 } // 视频播放完成的回调方法 public void onCompletion(MediaPlayer mp) throws IllegalStateException { if (currentPlay == 0) { MediaVideo.justPlay = false; } } // public void onBufferingUpdate(MediaPlayer mp, int percent) throws IllegalStateException { } // SurfaceView的callBack private class SurfaceCallback implements SurfaceHolder.Callback { public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) { } public void surfaceCreated(SurfaceHolder holder) { if (position > 0) { loadSrc(currentPlay); } } public void surfaceDestroyed(SurfaceHolder holder) { // 界面销毁,即将跳转到另外一个界面 if (mediaPlayer.isPlaying()) { justBack = true; position = mediaPlayer.getCurrentPosition(); mediaPlayer.stop(); } } } public boolean onError(MediaPlayer mp, int what, int extra) { return false; } }
推荐一个写的不错的MediaPlayer的文章:点击打开链接