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已經被創建出來了。
下面是封裝的操作播放視頻的代碼,因爲需要,加了一些判斷,不過基本的封裝都有。
[java] view plaincopy
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的文章:點擊打開鏈接