不积跬步,无以至千里;不积小流,无以成江海。要沉下心来,诗和远方的路费真的很贵!
参考博客:MediaPlayer的状态图和生命周期
MediaPlayer
是Android
中的多媒体播放类,其可以控制音视频、流文件或者本地音视频资源的播放过程。
下图为MediaPlayer
的整个生命周期的状态图。
上图中,蓝色椭圆形代表了MediaPlayer
的各个状态,弧线代表了状态改变之间的方法。其中单箭头弧表示同步函数的调用,双箭头弧表示异步函数的调用。
MediaPlayer
从Idle
状态到End
状态的过程,就是其生命周期。
new
方法,去创建MediaPlayer
实例。MediaPlayer
的reset()
方法。MediaPlayer
的release()
方法。MediaPlayer
处于End
状态时,它将不能再被使用,这个时候不能再回到MediaPlayer
的其他状态,因为本次生命周期已经终止。在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
状态。
setDataSource()
类型的方法,会使处于Idle
状态的对象迁移到Initialized
状态。MediaPlayer
处于其它的状态下,调用setDataSource()
方法,会抛出IllegalStateException
异常。MediaPlayer
对象必须要进入Prepared
状态。Prepared
状态,可以使用同步和异步两种方法。prepare()
,会在该对象进入Prepared
状态后返回。prepareAsync()
,会在该对象在Preparing
状态就返回,需要注册OnPreparedListener.onPrepared()
监听方法,判断是否进入Prepared
状态。MediaPlayer
对象进入了Prepared
状态,才可以对音视频的属性进行调整。prepareAsync()
方法进入。MediaPlayer
对象位于Prepared
状态后,使用start()
方法进入Started
状态。MediaPlayer
已经处于Started
状态,再调用start()
函数是没有任何作用的。当MediaPlayer
对象位于Started
状态后,使用pause()
方法进入Paused
状态。
当MediaPlayer
对象位于Paused
状态后,使用start()
方法令其重新播放。
如果MediaPlayer
已经处于Paused
状态,再调用pause()
函数是没有任何作用的。
Started
状态和Paused
状态之间的转换是瞬间的,在播放器内部是一个异步过程。
当调用stop()
函数时,MediaPlayer
无论正处于Started
、Paused
、Prepared
或 PlaybackCompleted
中的哪种状态,都将进入Stopped
状态。
一旦处于Stopped
状态,start()
方法将不能开始,直到重新调用prepare()
或prepareAsync()
函数,且处于Prepared
状态时才可以开始。
如果MediaPlayer
已经处于Stopped
状态,再调用stop()
函数是没有任何作用的。
seekTo
函数可以在其他状态下被调用,如Prepared
、Paused
及PlaybackCompleted
状态。
当前播放的位置可以通过getCurrentPosition
函数获取,可以跟踪播放器的播放进度。
当MediaPlayer
播放到数据流的末尾时,一次播放过程完成。
在MediaPlayer
中事先调用setLooping(boolean)
并设置为true
,表示循环播放,MediaPlayer
依然处于Started
状态。
如果调用setLooping(boolean)
并设置为false
,并且事先在MediaPlayer
上注册过 setOnCompletionListener
监听,那么播放器内部将回调onCompletion
函数。这就表明 MediaPlayer
开始进入PlaybackCompleted
状态。
当处于PlaybackCompleted
状态时,调用start()
函数,将重启播放器从头开始播放数据。
上述从Idle
状态到End
状态的过程,就是MediaPlayer
的生命周期。
状态之间的改变,使用什么函数,有要求。必须位于哪个状态,才可以使用哪些函数去进行状态之间的改变。否则会抛出不合法异常——IllegalStateException
。
使用函数时,需要注意其当前状态,所以了解其生命周期更有利于我们使用其进行音视频播放控制。