音视频文件和流的播放控制是通过状态机控制的。
一:MediaPlayer的状态图:(单箭头弧表示同步方法调用,双箭头弧表示异步方法调用)
1:当MediaPlayer对象通过new创建时或者通过调用reset()复原时,它的状态是Idle状态。当调用release()之后它的状态是End状态。MediaPlayer的生命周期是在这两个状态之间的。
通过new创建的MediaPlayer对象和通过reset()复原得到的MediaPlayer对象进入Idle状态是有重要区别的,通过这两种方式进入的Idle状态时调用如下方法都会导致程序错误:
getCurrentPosition(), getDuration()
, getVideoHeight()
, getVideoWidth()
, setAudioStreamType(int)
,setLooping(boolean)
, setVolume(float, float)
, pause()
, start()
, stop()
, seekTo(int)
, prepare()
orprepareAsync()
。如果是通过创建MediaPlayer对象进入的Idle状态时调用的这些方法,将保持状态不变,但是如果是通过reset()复原得到MediaPlayer对象进入的Idle状态时调用这些方法,将触发OnErrorListener.onError()这个方法,状态将转移到Error状态。
建议当MediaPlayer将时间不再使用时,立即调用release()方法。这样被与MediaPlayer对象相关的内部引擎占用的资源将可以被立即释放。一旦MediaPlayer处于End状态将没有办法使它回到其他状态。
由new创建的MediaPlayer对象处于Idle状态,而用creat()方法创建的MediaPlayer对象处于Prepared状态。
2.一般来说,一些播放控制操作可能由于各种原因失败,如不支持的音频/视频格式,分辨率过高,流超时等。因此,在这种情况下的错误报告和恢复需要重点关注。有时候由于程序错误,会在错误的状态执行播放控制操作。如果这时候通过setOnErrorListener(android.media.MediaPlayer.OnErrorListener)提前注册了OnErrorListener,那么播放器的内部引擎将调用OnErrorListener.onError()方法。
一旦错误发生,MediaPlayer对象将进入错误状态。
为了将MediaPlayer对象从Error状态中恢复,可以调用reset()方法将对象恢复到Idle状态。
在应用程序中注册一个OnErrorListenner来从内部发现错误并通知外部的播放器引擎是一个不错的编程实践。
通过抛出IllegalStateException异常的方式防止程序出现在错误状态调用prepare()、prepareAsync()等方法。
3.调用setDataSource(FileDescriptor)
, or setDataSource(String)
, or setDataSource(Context, Uri)
, orsetDataSource(FileDescriptor, long, long)方法让MediaPlayer对象从Idle状态转移到Initialized状态。
如果在其他状态调用setDataSource()将抛出IllegalStateException异常。
4.在MediaPlayer实例可以开始播放操作前应该先进入Prepared状态。
有两种方式可以进入准备状态:在调用完prepare()(同步)方法后状态立刻转移到Prepared状态;调用prepareAsync()(异步)方法后对象首先转移至Preparing状态,此时内部播放引擎继续完成剩下的准备工作直至准备工作完成。如果通过setOnPreparedListener(android.media.MediaPlayer.OnPreparedListener)提前注册成功了OnPreparedListener,当准备工作完成或者是prepare()方法返回后,内部播放引擎将调用OnPreparedListener接口的onPrepared()方法。
Preparing是暂时的状态。
如果在其他状态调prepare()或prepareAsync()方法将抛出lStateException异常。
当处于Prepared状态时,一些特性比如音视频的音量等可以通过调用相应的方法调整。
5.想要开始播放音视频文件,start()方法必须被调用。当成功调用start()方法后,MediaPlayer对象将处于Started状态。
当处于Started状态时,如果已经通过 setOnBufferingUpdateListener(OnBufferingUpdateListener)提前注册了OnBufferingUpdateListener,内部引擎将调用OnBufferingUpdateListener.onBufferingUpdate()回调方法。这个回调允许流媒体时当应用程序跟踪缓冲状态。
调用start()方法不会影响到已经处于Started状态的MediaPlayer对象。
6.播放可以暂停和停止并且当前播放位置可以调整。播放通过pause()方法暂停。当调用完pause()方法,MediaPlayer对象处于Paused状态。
在调用isPlaying()方法前需要一些时间让状态更新。
可以调用start()方法从暂停状态中恢复播放,并且进入Started状态。
调用paused()方法对已经处于Paused状态的MediaPlayer对象没有影响。
7.调用stop()方法可以停止播放,并且让MediaPlayer对象从Started, Paused, Prepared 或PlaybackCompleted状态进入Stopped状态。
一旦进入Stopped状态,只有当调用 prepare()或prepareAsync()方法后可以设置MediaPlayer对象进入Prepared状态。
调用stop()方法对已经处于Stopped状态的MediaPlayer对象没有影响。
8.播放位置可以通过调用 seekTo(int)方法调整。
虽然异步seekTo(int)调用可以立刻返回,但是事实上seek操作需要花费一些时间来完成,特别是流式音视频文件时。
如果OnSeekCompleteListener已经提前通过 setOnSeekCompleteListener(OnSeekCompleteListener)注册完成,一旦seek操作完成,内部播放引擎会调用OnSeekComplete.onSeekComplete()方法。
seekTo(int)方法也可以在其它状态时被调用,比如 Prepared, Paused 和PlaybackCompleted 状态。
实际的当前播放位置可以通过调用 getCurrentPosition()方法获取,这有助于音乐播放器等应用程序跟踪播放进度。
9.当播放到达末尾时,播放结束。
如果播放的循环模式设置为真,则回到Started状态。否则,如果 OnCompletionListener 已经提前通过setOnCompletionListener(OnCompletionListener)注册了,播放引擎调用OnCompletion.onCompletion()方法,处于PlaybackCompleted状态。
当播放完成后,调用start()重新开始播放音视频文件。
二:回调
通过调用对应方法设置相应监视器。……
三:一些接口说明
四:一些常量
五:方法说明
http://wear.techbrood.com/reference/android/media/MediaPlayer.html#setOnCompletionListener(android.media.MediaPlayer.OnCompletionListener)