1、概念
MediaPlayer是Android原生的多媒体播放器,可以用它来实现本地或者在线音视频的播放。
2、MediaPlayer的状态
下面的图是官方给出的状态转换图,也可易理解为MediaPlayer的生命周期。
- 椭圆形:表示MediaPlayer的状态;
- 弧形:表示驱动对象状态转换的控制操作,有两种类型的弧,具有单箭头的弧表示同步方法调用,而具有双箭头的弧表示异步方法调用。
MediaPlayer状态转换说明:
-
Idle状态:当新建对象或者在对象创建之后调用reset()时,MediaPlayer对象处于Idle状态。
-
End状态:Idle状态下,调用方法release()会直接进入End状态。MediaPlayer对象处于End状态,就无法再使用它,也无法将其恢复为其他任何状态。
生命周期开始 : 进入 Idle (闲置) 状态;
生命周期结束 : 进入 End (结束) 状态;
-
Initialized状态:Idle状态下,调用setDataSource()设置视频资源,正常情况下MediaPlayer对象会进入Initialized状态。如果调用setDataSource()方法的时候,MediaPlayer对象不是处于Idle状态就会抛出异常IllegalStateException。
-
Error状态:如果设置了回调setOnErrorListener(),此时遇到音频/视频格式不支持的,分辨率太高,流式传输超时等问题时,会回调onError()方法,此时进入Error状态。可以使用 reset() 方法进入Idle 状态。
-
Prepared状态:Initialized状态下,调用prepared()方法或preparedAsync()方法进入Prepared状态。prepared()方法直接进入Parpared状态,preparedAsync()方法是异步执行,会先进入Preparing状态,播放引擎准备完毕后会通过OnPreparedListener.onPrepared()回调方法通知进入Prepared状态。
只有在 Initialized状态下才能调用 prepare() 和 prepareAsync()方法, 在其它状态下调用就会抛出异常IllegalStateException。
创建 MediaPlayer : 通过 new MediaPlayer() 创建的对象处于Idle (闲置) 状态;
重载 MediaPlayer : 通过 create() 方法创建的 MediaPlayer 对象处于Prepare (准备) 状态;
因此使用create() 方法创建后不需要在调用prepared()方法或preparedAsync()方法,否则会报错。
-
Started状态:Prepared状态下,调用start()方法进入Started()状态。isPlaying()可以测试MediaPlayer对象是否处于Started状态。在Started状态时,可以通过setOnBufferingUpdateListener()在其OnBufferingUpdateListener.onBufferingUpdate()回调中对流播放缓冲的状态进行追踪,可以做加载进度显示。
-
Pause状态:Started状态下,调用 pause()暂停,MediaPlayer对象将进入Pause状态。调用start()方法重新进入Started状态,继续播放。pause()和start()方法是成对的。
-
Stopped状态:在Started状态时,调用stop()方法会使MdiaPlayer从Started、Paused、Prepared、PlaybackCompleted等状态进入到Stoped状态,播放停止。处于Stopped状态,就无法开始播放,直到调用prepare()或prepareAsync()将MediaPlayer对象重新设置为Prepared状态。
-
PlaybackCompleted状态:当视频播放完成之后,如果设置setLooping()为false,并且设置了回调setOnCompletionListener(),会执行OnCompletion.onCompletion()方法,在回调后进入PlaybackCompleted状态。在此状态里可以调用start()方法重新进入Started状态。
如果设置setLooping()为true,开启了循环模式,播放完毕之后MediaPlayer会重新进入Started状态。
3、MediaPlayer回调接口
- OnBufferingUpdateListener
该接口的作用是在流媒体缓冲状态发生改变的时候回调,percent表示已经缓冲了的或者播放了的媒体流百分比。
mPlayer.setOnBufferingUpdateListener(new MediaPlayer.OnBufferingUpdateListener() {
@Override
public void onBufferingUpdate(MediaPlayer mp, int percent) {
mBufferPercentage = percent;
}
}
- OnCompletionListener
在媒体流播放完毕之后回调。可以在该回调中设置播放下一个视频文件。
mPlayer.setOnCompletionListener(new MediaPlayer.OnCompletionListener() {
@Override
public void onCompletion(MediaPlayer mp) {
}
}
- OnErrorListener
在异步操作中出现错误时会回调该方法, 其它情况下出现错误时直接抛出异常。
what:出现的错误类型。
extra:针对与具体错误的附加码, 用于定位错误更详细信息。
mPlayer.setOnErrorListener(new MediaPlayer.OnErrorListener() {
@Override
public boolean onError(MediaPlayer mp, int what, int extra) {
return false;
}
}
- OnInfoListener
该方法在媒体播放时出现信息或者警告时回调该方法。
what:信息或者警告的类型。
extra:信息或者警告的附加码,关于警告更详细信息。
mGamePlayer.setOnInfoListener(new MediaPlayer.OnInfoListener() {
@Override
public boolean onInfo(MediaPlayer mp, int what, int extra) {
return false;
}
}
- OnPreparedListener
该方法在进入Prepared状态并开始播放的时候回调。
mPlayer.setOnPreparedListener(new MediaPlayer.OnPreparedListener() {
@Override
public void onPrepared(MediaPlayer mp) {
//这里可以调用start()方法开始播放视频
mPlayer.start();
}
}
- OnSeekCompleteListener
查找操作完成的时候回调该方法。
mPlayer.setOnSeekCompleteListener(new MediaPlayer.OnSeekCompleteListener() {
@Override
public void onSeekComplete(MediaPlayer mediaPlayer) {
}
}
- OnVideSizeChangedListener
当视频大小首次加载的时候及视频大小更新时回调该方法,如果没有视频返回0。
mPlayer.setOnVideoSizeChangedListener(new MediaPlayer.OnVideoSizeChangedListener() {
@Override
public void onVideoSizeChanged(MediaPlayer mp, int width, int height) {
}
}
4、MediaPlayer常用函数
-
seekTo():
调整播放位置可以通过seekTo()方法,由于seekTo()是异步的,实际上查找需要一定时间才能完成,实际的查找位置完成时会走setOnSeekCompleteListener()的OnSeekComplete.onSeekComplete()回调。
seekTo()在Prepared,Paused和PlaybackCompleted 状态下执行仍然会保持当前的状态。 -
setDataSource():设置数据源,正常调用后会进入Initialized状态。
-
setAudioStreamType():设置音频流类型,设置方式如下。
mGamePlayer.setAudioStreamType(AudioManager.STREAM_MUSIC);
- setDisplay(): 设置播放视频的SurfaceHolder,设置方式如下,使用SurfaceView播放的时候使用该方法。
SurfaceView surfaceView = findViewById(R.id.surfaceView);
SurfaceHolder surfaceHolder = surfaceView.getHolder()
mPlayer.setDisplay(surfaceHolder);
- setSurface(): 设置播放视频的Surface,设置方式如下,需要在SurfaceTexture准备就绪onSurfaceTextureAvailable回调的时候设置,使用TextureView播放的时候使用该方法。
mTextureView.setSurfaceTextureListener(new TextureView.SurfaceTextureListener() {
@Override
public void onSurfaceTextureAvailable(SurfaceTexture surface, int width, int height) {
// SurfaceTexture准备就绪
mPlayer.setSurface(new Surface(surface));
}
@Override
public void onSurfaceTextureSizeChanged(SurfaceTexture surface, int width, int height) {
// SurfaceTexture缓冲大小变化
}
@Override
public boolean onSurfaceTextureDestroyed(SurfaceTexture surface) {
// SurfaceTexture即将被销毁
return false;
}
@Override
public void onSurfaceTextureUpdated(SurfaceTexture surface) {
// SurfaceTexture通过updateImage更新
}
});
-
setVolume(): 设置音量。
-
getCurrentPosition():获取当前播放器播放的位置,返回值是已经播放了的毫秒数。
-
getDuration():获取文件的播放时长 (毫秒),如果没有可用的时长,就会返回 -1。
参考文章:
用MediaPlayer+TextureView封装一个完美实现全屏、小窗口的视频播放器
MediaPlayer+TextureView实现视频播放器
【Android 多媒体开发】 MediaPlayer 状态机 接口 方法 解析