public class MediaPlayer
extends Object
MediaPlayer class 能够用来使用来控制vudio/video(音频或视频)文件和流文件的播放.举个例子可以在
VideoView 中了解怎么样使用这些方法。
请看Audio and Video 中附加的文档。
MedioPlayer状态图如下:
audio/video(音频/视频)文件和流的控制是通过状态机制管理的。以下图标显示了 MediaPlayer
对象在播
放控制操作支持下被执行的生命周期和状态。椭圆代表MedioPlayer对象可能驻留的状态。弧线代表播放控制
操作驱使对象的状态间的转换。这里有两种弧线类型。单箭头的弧线代表同步的方法调用,而双箭头的弧线代
表异步的方法调用。
从状态图,我们可以知道MedioPlayer对象有以下的状态:
1
) 当使用new或调用reset()后MedioPlayer对象就会被创建,对象将处在Idle状态;并且当release()被调用后,
对象将处于End状态。 这两种状态之间是MedioPlayer对象的生命周期。
1.1) 这里有点微妙但又很重要的不同是在MedioPlayer对象的创建和创建并调用reset()之后的MedioPlayer对象中。
在Idle状态时调用例如getCurrentPosition()
, getDuration()
, getVideoHeight()
, getVideoWidth()
,
setAudioStreamType(int)
, setLooping(boolean)
, setVolume(float, float)
, pause()
, start()
, stop()
,seekTo(int)
,
prepare()
or prepareAsync() 这些方法,都
是
编程的错误。在MediaPlayer对象被构建后如果这些方法被调用,框架将无法被
内部的播放引擎回调OnErrorListener.onError() 并且对象的状态不会改变。但如果MediaPlayer对象调用了reset()之后,调
用这些方法,内部的播放引擎将能够回调 OnErrorListener.onError()方法,并且对象会转入Error状态。
1.2)并且推荐一旦MediaPlayer不再使用,就立即调用release()方法那么内部播放引擎对这个MediaPlayer对象的关联将会立即释放资源。
资源包括单一
的资源例如计算机加速硬件组件(可理解为只能够一个对象使用的资源),所以若没有调用release()方法可能会导致后面
的MediaPlayer对象无法使用这单一资源
从而退回到软件实现或运行失败,一旦MediaPlayer对象进入了End状态,它将不再被使
用,并且没有办法回到其他任何状态。
1.3)此外,使用new创建的MediaPlayer对象将处于Idle状态,然而那些通过重载的create()便利方法创建的MediaPlayer对象却不是出在Idle状态。
实际上,如果
成功调用create()方法,那么这些对象将是处在
Prepared状态。
2)通常,一些播放控制操作由于各种各样的原因而运行失败,例如 audio/video的格式不支持;缺少隔行扫描的audio/video;分表率太高;流超时等此类原因。
那么,错误的报告和恢复在这些情况下是重要的。有时,由于程序设计的错误,在一个无效的状态下调用一个播放控制操作也可能发生。在所有这些错误条件下,
内部的播放引擎会调用一个由客户端程序员提供的OnErrorListener.onError()方法。客户端程序员可以通过调用Medialayer.setOnErrorListener(android.media.
MediaPlayer.OnErrorListener)方法来注册OnErrorListener.
2.1)一旦错误发生,值得注意的是,MediaPlayer对象会进入Error状态,即使没有注册OnErrorListener,应用还是会进入Error状态。
2.2)为了重新使用在Error状态的MediaPlayer对象使它从Error状态恢复,那么reset()方法的调用能够恢复对象到Idle状态。
2.3)一个好的程序设计实践你的应用,是有注册一个OnErrorListener用来注意来自内部播放引擎的Error的通知。
2.4)在一个invalid状态下, 例如调用prepare()
, prepareAsync()
,或者一个重写的setDataSource方法。IlleglStateException异常被抛出,可以防止程序设计的错误.。
3)调用setDataSource(FileDescriptor)方法,或setDataSource(String)方法,或setDataSource(Context,Uri)方法,
或setDataSource(FileDescriptor,long,long)方法会使处于Idle状态的对象迁移到Initialized状态。
3.1)若当对象在任何一个其他状态下调用setDataSource()会抛出 IllegalStateException 异常。
3.2)好的编程习惯是不要疏忽了调用setDataSource()方法的时候可能会抛出的IllegalArgumentException异常和IOException异常。
4)一个MedioPlayer对象在播放开始之前必须首先进入Prepared状态。
4.1)有两种方法(同步和异步)可以使MediaPlayer对象进入Prepared状态:要么调用prepare()方法(同步),
此方法返回就表示该MediaPlayer对象已经进入了Prepared状态;要么调用prepareAsync()方法(异步),此方法会使此
MediaPlayer对象进入Preparing状态并返回,而内部的播放引擎会继续未完成的准备工作。当同步版本返回时或异步版本
的准备工作完全完成时就会调用客户端程序员提供的OnPreparedListener.onPrepared()监听方法。可以调用MediaPlayer
.setOnPreparedListener(android.media.MediaPlayer.OnPreparedListener)方法来注册OnPreparedListener.
4.2)值得注意的是Preparing是个短暂的状态,在此状态下调用任何具备边影响的方法的结果都是未知的!
4.3)在任何其他状态下,调用prepare()和prepareAsync()方法会抛出IllegalStateException异常。
4.4)当MediaPlayer对象处于Prepared状态的时候,可以调用相应的方法调整音频/视频的属性,如音量,
播放时是否一直亮屏,循环播放等。
5)想要开始播放,start()必须需要调用。在
start()成功的调用之后,
MediaPlayer 对象将进入 Started的状态,isPlaying()方法可
以被调用来测试某个MediaPlayer对象是否在Started状态。
5.1)当在 Started状态,内部播放引擎会调用客户端程序员提供的OnBufferingUpdateListener.onBufferingUpdate()回调方法,
通过setOnBufferingUpdateListener(OnBufferingUpdateListener)注册监听。
此回调方法允许应用程序追踪流播放的缓冲的状态。
5.2)对一个已经处于Started 状态的MediaPlayer对象调用start()方法没有影响。
6)播放可以被暂停,停止,和调整当前的播放位置。当调用pause()方法并返回时,会使MediaPlayer对象进入Paused状态。
注意Started与Paused状态的相互转换在内部的播放引擎中是异步的。所以可能需要一点时间在isPlaying()方法中更新
状态,若在播放流内容,这段时间可能会有几秒钟。
6.1) 调用start()方法会让一个处于Paused状态的MediaPlayer对象从之前暂停的地方恢复播放。当调用start()方法
返回的时候,MediaPlayer对象的状态会又变成Started状态。
6.2) 对一个已经处于Paused状态的MediaPlayer对象pause()方法没有影响。
7) 调用stop()方法会停止播放,并且还会让一个处于Started,Paused,Prepared或PlaybackCompleted状态的MediaPlayer进入Stopped状态。
7.1)一旦MediaPlayer在Stopped状态,mediaPlayer不能开始播放,直到prepare() or prepareAsync()调用后,
使MediaPlayer再次进入Prepared状态之后。
7.2)对一个已经处于Stopped状态的MediaPlayer对象stop()方法没有影响。
8) 调用seekTo()方法可以调整播放的位置。
8.1)seekTo(int)方法是异步执行的,所以它可以马上返回,但是实际的定位播放操作可能需要一段时间才能完成,
尤其是播放流形式的音频/视频。当实际的定位播放操作完成之后,内部的播放引擎会调用客户端程序员提供的
OnSeekComplete.onSeekComplete()回调方法。可以通过setOnSeekCompleteListener(OnSeekCompleteListener)方法注册。
8.2)注意,seekTo(int)方法也可以在其它状态下调用,比如Prepared,Paused和PlaybackCompleted状态。
8.3)此外,目前的播放位置,实际可以调用getCurrentPosition()方法得到,它可以帮助如音乐播放器的应用程序不断更新播放进度
9) 当播放到流的末尾,播放就完成了。
9.1) 如果调用了setLooping(boolean)方法开启了循环模式,那么这个MediaPlayer对象会重新进入Started状态。
9.2) 若没有开启循环模式,那么内部的播放引擎会调用客户端程序员提供的OnCompletion.onCompletion()回调方法。
可以通过调用MediaPlayer.setOnCompletionListener(OnCompletionListener)方法来设置。内部的播放引擎一旦调
用了OnCompletion.onCompletion()回调方法,说明这个MediaPlayer对象进入了PlaybackCompleted状态。
9.3) 当处于PlaybackCompleted状态的时候,可以再调用start()方法来让这个MediaPlayer对象再进入Started状态。
参考文献:
1.谷歌官方Android SDK开发文档
2.http://my.oschina.net/zhangqingcai/blog/29660