目录
不积跬步,无以至千里;不积小流,无以成江海。要沉下心来,诗和远方的路费真的很贵!
【Android】MediaPlayer生命周期
参考博客:MediaPlayer的状态图和生命周期
-
MediaPlayer
是Android
中的多媒体播放类,其可以控制音视频、流文件或者本地音视频资源的播放过程。 -
下图为
MediaPlayer
的整个生命周期的状态图。
-
上图中,蓝色椭圆形代表了
MediaPlayer
的各个状态,弧线代表了状态改变之间的方法。其中单箭头弧表示同步函数的调用,双箭头弧表示异步函数的调用。 -
MediaPlayer
从Idle
状态到End
状态的过程,就是其生命周期。
1. Idle状态(就绪状态)
- 使用
new
方法,去创建MediaPlayer
实例。 - 使用
MediaPlayer
的reset()
方法。
2. End状态
- 使用
MediaPlayer
的release()
方法。 - 当
MediaPlayer
处于End
状态时,它将不能再被使用,这个时候不能再回到MediaPlayer
的其他状态,因为本次生命周期已经终止。
3. Error状态
-
在
MediaPlayer
调用reset()
函数之后 。上层应用调用getCurrentPosition()
,getDuration()
,getVideoHeight()
,getVideoWidth()
,setAudioAttributes(android.media.AudioAttributes)
,setLooping(boolean)
,setVolume(float, float)
,pause()
,start()
,stop()
,seekTo(long, int)
,prepare()
或者prepareAsync()
这些函数都会出错。 -
出错后会回调到用户提供的回调方法
OnErrorListener.onError()
,这时候MediaPlayer
就处于Error
状态。所以一旦不再使用MediaPlayer
,就需要调用release()
函数,以便MediaPlayer
资源得到合理的释放。 -
在一般情况下,由于种种原因一些播放控制操作可能会失败。如不支持的音频/视频格式,缺少隔行扫描的音频/视频,分辨率太高,流超时等原因。
-
一旦发生错误,
MediaPlayer
对象会进入到Error
状态。为了重用一个处于Error
状态的MediaPlayer
对象,可以调用reset()
方法来把这个对象恢复成Idle
状态。
4. Initialized状态
- 调用
setDataSource()
类型的方法,会使处于Idle
状态的对象迁移到Initialized
状态。 - 若当此
MediaPlayer
处于其它的状态下,调用setDataSource()
方法,会抛出IllegalStateException
异常。
5. Prepared状态
- 在开始播放之前,
MediaPlayer
对象必须要进入Prepared
状态。 - 进入
Prepared
状态,可以使用同步和异步两种方法。 - 同步方法——
prepare()
,会在该对象进入Prepared
状态后返回。 - 异步方法——
prepareAsync()
,会在该对象在Preparing
状态就返回,需要注册OnPreparedListener.onPrepared()
监听方法,判断是否进入Prepared
状态。 - 只有
MediaPlayer
对象进入了Prepared
状态,才可以对音视频的属性进行调整。
6. Preparing状态
- 使用
prepareAsync()
方法进入。
7. Started状态
- 当
MediaPlayer
对象位于Prepared
状态后,使用start()
方法进入Started
状态。 - 如果
MediaPlayer
已经处于Started
状态,再调用start()
函数是没有任何作用的。
8. Paused状态
-
当
MediaPlayer
对象位于Started
状态后,使用pause()
方法进入Paused
状态。 -
当
MediaPlayer
对象位于Paused
状态后,使用start()
方法令其重新播放。 -
如果
MediaPlayer
已经处于Paused
状态,再调用pause()
函数是没有任何作用的。 -
Started
状态和Paused
状态之间的转换是瞬间的,在播放器内部是一个异步过程。
9. Stopped状态
-
当调用
stop()
函数时,MediaPlayer
无论正处于Started
、Paused
、Prepared
或PlaybackCompleted
中的哪种状态,都将进入Stopped
状态。 -
一旦处于
Stopped
状态,start()
方法将不能开始,直到重新调用prepare()
或prepareAsync()
函数,且处于Prepared
状态时才可以开始。 -
如果
MediaPlayer
已经处于Stopped
状态,再调用stop()
函数是没有任何作用的。 -
seekTo
函数可以在其他状态下被调用,如Prepared
、Paused
及PlaybackCompleted
状态。
10. PlaybackCompleted状态
-
当前播放的位置可以通过
getCurrentPosition
函数获取,可以跟踪播放器的播放进度。 -
当
MediaPlayer
播放到数据流的末尾时,一次播放过程完成。 -
在
MediaPlayer
中事先调用setLooping(boolean)
并设置为true
,表示循环播放,MediaPlayer
依然处于Started
状态。 -
如果调用
setLooping(boolean)
并设置为false
,并且事先在MediaPlayer
上注册过setOnCompletionListener
监听,那么播放器内部将回调onCompletion
函数。这就表明MediaPlayer
开始进入PlaybackCompleted
状态。 -
当处于
PlaybackCompleted
状态时,调用start()
函数,将重启播放器从头开始播放数据。
总结
-
上述从
Idle
状态到End
状态的过程,就是MediaPlayer
的生命周期。 -
状态之间的改变,使用什么函数,有要求。必须位于哪个状态,才可以使用哪些函数去进行状态之间的改变。否则会抛出不合法异常——
IllegalStateException
。 -
使用函数时,需要注意其当前状态,所以了解其生命周期更有利于我们使用其进行音视频播放控制。