MediaPlayer的状态

MediaPlayer的状态

音频和视频的播放过程也就是MediaPlayer对象的状态转换过程。深入理解MediaPlayer的状态机是灵活驾驭OPhone多媒体编程的基础。图7-3是MediaPlayer的状态图,其中MediaPlayer的状态用椭圆形标记,状态的切换由箭头表示,单箭头代表状态的切换是同步操作,双箭头代表状态的切换是异步操作。

1. 创建与销毁

MediaPlayer可以通过静态方法MediaPlayer.create()或者new操作符来创建。这两种方法创建的MediaPlayer对象处于的状态是不同的,使用create()方法创建的MediaPlayer对象处于prepared状态,因为系统已经根据参数的资源ID调用了setDataSource()和prepare()方法;使用new操作符创建的MediaPlayer对象则处于idle状态。除了刚刚构建的MediaPlayer对象处于idle状态外,调用reset()方法后的MediaPlayer状态也同样处于idle状态。由于处于idle状态的MediaPlayer还没有设置数据源,无法获得多媒体的时长、视频的高度等信息,因此现在调用下列方法是典型的编程错误。对于刚刚创建的MediaPlayer对象调用如下方法,底层系统不会调用MediaPlayer注册的OnErrorListener,MediaPlayer的状态也不会改变。对于通过调用reset()方法进入idle状态的MediaPlayer对象调用如下方法,则会导致底层系统调用OnErrorListener.onError()方法,MediaPlayer对象将进入error状态。

 
(点击查看大图)图7-3  MediaPlayer的状态图

getCurrentPosition()

getDruation()

getVideoWidth()

getVideoHeight()

setAudioStreamType()

setLooping()

setVolume()

pause()

start()

stop()

seekTo()

prepare()

prepareAsync()

对于不再需要的MediaPlayer对象,一定要通过调用release()方法使其进入到end状态,因为这关系到资源的释放问题。如果MediaPlayer对象不释放硬件加速器等资源,随后创建的MediaPlayer对象就无法使用这唯一的资源,甚至导致创建失败。处于end状态的MediaPlayer意味着它的生命周期终结,无法再回到其他状态了。

2. 初始化

在播放音频和视频之前必须对MediaPlayer进行初始化操作,这主要由两步工作完成。调用重载的setDataSource()方法将使MediaPlayer对象进入到initialized状态,随后调用prepare()或者prepareAsync()方法将使MediaPlayer对象进入到prepared状态。由于prepareAsync()方式是异步调用,因此通常为MediaPlayer注册OnPreparedListener(),并在onPrepare()方法中启动播放器。当MediaPlayer对象处于prepared状态时,意味着调用者已经可以获得多媒体的时长等信息,此时可以调用MediaPlayer的相关方法设置播放器的属性。例如,调用setVolume(float leftVolume, float rightVolume)设置播放器的音量。

3. 播放、暂停和停止

调用start()方法,MediaPlayer将进入到started状态。isPlaying()方法可以用来判断MediaPlayer是否处在started状态。当MediaPlayer从网络上播放多媒体文件时,可以通过onBufferingUpdateListener.onBufferingUpdate(MediaPlayer mp,int percent)来监听缓冲的进度,其中percent是0~100的整数,代表已经缓冲好的多媒体数据的百分比。

调用pause()方法,MediaPlayer将进入到paused状态。需要注意的是,从started到paused、从paused到started状态的转换是异步过程,也就是说,可能经过一段时间才能更新MediaPlayer的状态。在调用isPlaying()来查询播放器的状态时需要考虑这一点。

调用stop()方法,MediaPlayer将进入到stopped状态。一旦MediaPlayer进入stopped状态,必须再次调用prepare()或者prepareAsyn()才能使其进入到prepared状态,以便复用此MediaPlayer对象,再次播放多媒体文件。

4. 快进和快退

调用seekTo()方法可以调整MediaPlayer的媒体时间,以实现快退和快进的功能。seekTo()方法也是异步的,方法会立即返回,但是媒体时间调整的工作可能需要一段时间才能完成。如果为MediaPlayer设置了onSeekCompleteListener,那么onSeekComplete()方法将被调用。需要说明的一点是,seekTo()不仅可以在started状态下调用,还可以在paused、prepared和playbackCompleted状态下调用。

5. 播放结束状态

如果播放状态自然结束,MediaPlayer可能进入两种可能的状态。当循环播放模式设置为true时,MediaPlayer对象保持started状态不变;当循环播放模式设置为false时,MediaPlayer对象的onCompletionListener.onCompletion()方法会被调用,MediaPlayer对象进入到playbackCompleted状态。对于处于playbackCompleted状态的播放器,再次调用start()方法,将重新播放音/视频文件。需要注意的是,当播放器结束时,音/视频的时长、视频的尺寸信息依然可以通过调用getDuration()、getVideoWidth()和getVideoHeight()等方法获得。

6. 错误处理

在播放器播放音/视频文件时,可能发生各种各样的错误,比如IO错误、多媒体文件格式错误等。正确处理播放过程中的各种错误显得尤为重要。为了监听错误信息,可以为MediaPlayer对象注册onErrorListener监听器,当错误发生时,onErrorListener.onError()方法会被调用,MediaPlayer对象进入到error状态。如果希望复用MediaPlayer对象并从错误中恢复过来,那么可以调用reset()方法使MediaPlayer再次进入到idle状态。总之,监视MediaPlayer的状态是非常重要的,在错误发生之际提示用户,并恢复播放器的状态才是正确的处理方法。

除了上述的错误之外,如果在不恰当的时间调用了某方法,则会抛出IllegalStateException异常,在程序中应该使用try/catch块捕获到此类的编程错误。

至此,我们已经详细地介绍了MediaPlayer的状态图,下面通过一个具体的媒体播放器实例向读者介绍如何使用MediaPlayer的相关API。

你可能感兴趣的:(Android知识点)