android media player 生命周期,android mediaPlayer的基本使用

1、MediaPlayer的生命周期

a849b5eb841d

MediaPlayer的状态图

有两种类型的弧,单箭头表示的是同步方法调用,有两个箭头代表异步方法调用

1、Idle 状态及End 状态

当使用new()方法创建一个MediaPlayer对象或者调用了其reset()方法时,该MediaPlayer对象处于idle状态。release()方法调用后进入End状态。

2、Initialized 状态

setDataSource()调用之后,MediaPlayer就进入Initialized状态,表示要播放的文件已经设置好了。如果setDataSource()在MediaPlayer的非Idle 状态调用,会抛出IllegalStateException异常

3、Prepared状态

MediaPlayer准备好了

prepare():同步方法,调用这个方法,MediaPlayer就进入Prepared状态

prepareAsync():异步方法,经过Preparing 状态,在准备工作结束之后,进入Prepared状态,会回调OnPreparedListener.onPrepared()。

在Prepared状态之后,就可以调用MediaPlayer的一些set方法了,如,setScreenOnWhilePlaying()、setVolume()、setLooping()。

4、Started 状态,Paused 状态

在MediaPlayer准备好之后,调用start()方法,此时MediaPlayer就处于Started状态;调用pause()方法,MediaPlayer进入Paused状态。

如果注册过OnBufferingUpdateListener,在Started 状态时,MediaPlayer就会回调onBufferingUpdate()方法,可以使应用程序保持跟踪视频流的缓冲

5、Stopped 状态

当MediaPlayer处于Started 、Paused 、Prepared、PlaybackCompleted状态下,均可调用stop()停止MediaPlayer,而处于Stopped状态的MediaPlayer要想重新播放,需要通过prepareAsync()(prepare())方法回到Prepared状态才可以。

6、PlaybackCompleted状态

文件正常播放完毕,而又没有设置循环播放的话就进入该状态,并会触发OnCompletionListener的onCompletion()方法。

7、Error 状态

如果由于某种原因MediaPlayer出现了错误,会触发OnErrorListener.onError()事件,此时MediaPlayer即进入Error状态

注意:

1、MediaPlayer会消耗系统的资源,需要在适当的时候把不需要的资源释放掉。例如,如果在Activity中调用onStop()方法时,需要释放MediaPlayer。当Activity恢复或者重新启动时,需要创建一个新的MediaPlayer并且重新准备。

释放MediaPlayer

mediaPlayer.release();

mediaPlayer = null;

2、SurfaceView

SurfaceView是配合MediaPlayer,将一帧一帧的图像,显示在界面上。

指定MediaPlayer显示图像

void setDisplay(SurfaceHolder holder)

SurfaceHolder可以理解为SurfaceView装载需要显示的一帧帧图像的容器,它可以通过SurfaceHolder.getHolder()方法获得。

SurfaceView,通过双缓冲的机制来显示帧图像。双缓冲可以理解为有两个线程轮番去 解析视频流的帧图像,当一个线程解析完帧图像后,把图像渲染到界面中,同时另一线程开始解析下一帧图像,使得两个线程轮番配合去解析视频流,以达到流畅播放的效果。

SurfaceView内部实现了双缓冲的机制,但是实现这个功能是非常消耗系统内存的。因为移动设备的局限性,Android在设计的时候规 定,SurfaceView如果为用户可见的时候,创建SurfaceView的SurfaceHolder用于显示视频流解析的帧图片,如果发现 SurfaceView变为用户不可见的时候,则立即销毁SurfaceView的SurfaceHolder,以达到节约系统资源的目的。所以,需要去维护一个SurfaceHolder,需要用到它的一个回调,SurfaceHolder.Callback()

public interface Callback {

public void surfaceCreated(SurfaceHolder holder);

public void surfaceChanged(SurfaceHolder holder, int format, int width, int height);

public void surfaceDestroyed(SurfaceHolder holder);

}

3、使用

/**

* todo public

* 加载视频

*/

public void loadAndPlay(String videoUrl){

this.videoUrl=videoUrl;

surfaceView.getHolder().setKeepScreenOn(true);

surfaceView.getHolder().addCallback(new SurfaceViewCallback());

}

/**

* 当用户不可见的时候 ,SurfaceHolder 就会销毁,当再次可见的时候,会创建新的SurfaceHolder;

* 使用SurfaceHolder.Callback()维护一个SurfaceHolder

*/

class SurfaceViewCallback implements SurfaceHolder.Callback {

@Override

public void surfaceCreated(SurfaceHolder holder) {

if(mediaPlayer==null){

mediaPlayer=new MediaPlayer();

mediaPlayer.setDataSource(videoUrl);

mediaPlayer.setAudioStreamType(AudioManager.STREAM_MUSIC);

mediaPlayer.setOnPreparedListener(this);

mediaPlayer.setOnBufferingUpdateListener(this);

mediaPlayer.setOnErrorListener(this);

mediaPlayer.setOnCompletionListener(new MediaPlayerCompletion());

mediaPlayer.prepareAsync();

mediaPlayer.setDisplay(surfaceView.getHolder());

}

}

@Override

public void surfaceDestroyed(SurfaceHolder holder) {

isVideoPrepared=false;

if(mediaPlayer!=null){

mediaPlayer.release();

mediaPlayer=null;

}

}

}

/**

* 视频准备好回调

*/

@Override

public void onPrepared(MediaPlayer mp) {

isVideoPrepared=true;

mediaPlayer.start();

mediaPlayer.setScreenOnWhilePlaying(true);

}

private boolean isVideoPrepared;

a849b5eb841d

S70326-182808.jpg