MediaPlayer 详解

来源:互联网 发布:上海巨人网络待遇 编辑:程序博客网 时间:2024/06/05 00:42
public class

MediaPlayer

extends Object
java.lang.Object   ↳android.media.MediaPlayer

Class Overview


MediaPlayer class can be used to control playback of audio/video files and streams. An example on how to use the methods in this class can be found in VideoView.

Topics covered here are:

  1. State Diagram
  2. Valid and Invalid States
  3. Permissions
  4. Register informational and error callbacks

Developer Guides

For more information about how to use MediaPlayer, read the Media Playback developer guide.

State Diagram

Playback control of audio/video files and streams is managed as a state machine. The following diagram shows the life cycle and the states of a MediaPlayer object driven by the supported playback control operations. The ovals represent the states a MediaPlayer object may reside in. The arcs represent the playback control operations that drive the object state transition. There are two types of arcs. The arcs with a single arrow head represent synchronous method calls, while those with a double arrow head represent asynchronous method calls.

MediaPlayer State diagram


翻译:

MediaPlayer 这个类用于控制视频、音频、流文件的播放控制。VideoView中有怎么使用这些方法的示例代码。

注意:上面的MediaPlayer的状态转换图很重要【越看越像数电中的状态机】

两个箭头的方法:异步方法
一个箭头的方法:同步方法

From this state diagram, one can see that a MediaPlayer object has the following states:

  • When a MediaPlayer object is just created using new or after reset() is called, it is in the Idle state; and after release() is called, it is in the End state. Between these two states is the life cycle of the MediaPlayer object.
    • There is a subtle but important difference between a newly constructed MediaPlayer object and the MediaPlayer object after reset() is called. It is a programming error to invoke methods such as getCurrentPosition()getDuration()getVideoHeight()getVideoWidth()setAudioStreamType(int)setLooping(boolean),setVolume(float,float)pause()start()stop()seekTo(int)prepare() or prepareAsync() in the Idle state for both cases. If any of these methods is called right after a MediaPlayer object is constructed, the user supplied callback method OnErrorListener.onError() won't be called by the internal player engine and the object state remains unchanged; but if these methods are called right after reset(), the user supplied callback method OnErrorListener.onError() will be invoked by the internal player engine and the object will be transfered to the Error state.
    • It is also recommended that once a MediaPlayer object is no longer being used, call release() immediately so that resources used by the internal player engine associated with the MediaPlayer object can be released immediately. Resource may include singleton resources such as hardware acceleration components and failure to call release() may cause subsequent instances of MediaPlayer objects to fallback to software implementations or fail altogether. Once the MediaPlayer object is in the End state, it can no longer be used and there is no way to bring it back to any other state.
    • Furthermore, the MediaPlayer objects created using new is in the Idle state, while those created with one of the overloaded convenient create methods are NOT in theIdle state. In fact, the objects are in the Prepared state if the creation using create method is successful.
  • In general, some playback control operation may fail due to various reasons, such as unsupported audio/video format, poorly interleaved audio/video, resolution too high, streaming timeout, and the like. Thus, error reporting and recovery is an important concern under these circumstances. Sometimes, due to programming errors, invoking a playback control operation in an invalid state may also occur. Under all these error conditions, the internal player engine invokes a user supplied OnErrorListener.onError() method if an OnErrorListener has been registered beforehand via setOnErrorListener(android.media.MediaPlayer.OnErrorListener).
    • It is important to note that once an error occurs, the MediaPlayer object enters the Error state (except as noted above), even if an error listener has not been registered by the application.
    • In order to reuse a MediaPlayer object that is in the Error state and recover from the error, reset() can be called to restore the object to its Idle state.
    • It is good programming practice to have your application register a OnErrorListener to look out for error notifications from the internal player engine.
    • IllegalStateException is thrown to prevent programming errors such as calling prepare()prepareAsync(), or one of the overloaded setDataSource methods in an invalid state.
获取MediaPlayer对象的两种方法:new 和 reset( )。
执行new 或 reset( )后,mediaPlayer处于idle状态。        ------ 生命之开始
执行 release( )                                   ---------------------------- 生命之终结

new 和 reset( ) 获取到的MediaPlayer实例,两者有微妙,但是重要的区别:
1、idel状态下执行: getCurrentPosition()getDuration()getVideoHeight()getVideoWidth()setAudioStreamType(int)setLooping(boolean),
   setVolume(float,float)pause()start()stop()seekTo(int)prepare() or prepareAsync() 都会报错
              new 出来的,不会回调:OnErrorListener.onError() ,状态保持不变。
              reset( ) 的,会回调: OnErrorListener.onError() ,变成 Error 状态。
这个是 player engine 写好的

2、推荐:一旦MediaPlayer不用了,那么就应该马上释放。资源中可能有包括单例资源:比如,硬件加速组件。
调用 release( ) 失败,会导致下一个MediaPlayer实例使用的时候出异常或者完全失败【单例资源是临界资源,还没释放呢!】
一旦MediaPlayer处于:End状态了,那么就不会再变成其他状态了。只能由其他状态变成End状态,不可逆。
3、除此之外,new 出来的MediaPlayer对象:处于idel状态。用create(xxx)得到的MediaPalyer对象不是idel状态,事实上,create方法执行成功的话,得到的MediaPalyer实例处于Prepared状态。
==================================================================================================================================================
总而言之,播放操作会因为多种原因而失败。
比如:视频,音频格式不支持,分辨率太高,网络超时.........
所以,Error Report 和 Error 修复是很重要的。
有时候,由于程序错误,可能导致播放操作处于一种不可用的状态。在这些错误状态下,mediaPlayer给用户提供了回调方法:
OnErrorListener.onError() 【但是需要先注册: setOnErrorListener(android.media.MediaPlayer.OnErrorListener).
1、一旦有Error发生,那么MediaPlayer就进入到Error状态【即使OnErrorListener设置好了
2、为了复用发生错误的 MediaPlayer【此时处于Error状态】,调用 reset(),就能使得MediaPlayer进入到 idel 状态。
3、给自己的App设置错误监听器是很必要的,可以查看错误信息
4、调用  prepare()prepareAsync(), 或者在不合适的状态下调用 setDataSource ,会抛出IllegalStateException,
这样以便于阻止 MediaPlayer进入 Error 状态。

  • Calling setDataSource(FileDescriptor), or setDataSource(String), or setDataSource(Context, Uri), or setDataSource(FileDescriptor, long, long) transfers a MediaPlayer object in the Idle state to the Initialized state.
    • An IllegalStateException is thrown if setDataSource() is called in any other state.
    • It is good programming practice to always look out for IllegalArgumentException and IOException that may be thrown from the overloaded setDataSource methods.
  • A MediaPlayer object must first enter the Prepared state before playback can be started.
    • There are two ways (synchronous vs. asynchronous) that the Prepared state can be reached: either a call to prepare() (synchronous) which transfers the object to thePrepared state once the method call returns, or a call to prepareAsync() (asynchronous) which first transfers the object to the Preparing state after the call returns (which occurs almost right way) while the internal player engine continues working on the rest of preparation work until the preparation work completes. When the preparation completes or when prepare() call returns, the internal player engine then calls a user supplied callback method, onPrepared() of the OnPreparedListener interface, if an OnPreparedListener is registered beforehand via setOnPreparedListener(android.media.MediaPlayer.OnPreparedListener).
    • It is important to note that the Preparing state is a transient state, and the behavior of calling any method with side effect while a MediaPlayer object is in the Preparingstate is undefined.
    • An IllegalStateException is thrown if prepare() or prepareAsync() is called in any other state.
    • While in the Prepared state, properties such as audio/sound volume, screenOnWhilePlaying, looping can be adjusted by invoking the corresponding set methods.
关于:setDataSource(XX.....)的说明:
1、必须在idel状态时候调用,这个方法会让 MediaPlayer从idel状态进入到 Initialized状态。
     在其他状态调用此方法时候,会抛出 IllegalStateException。

关于:Prepared状态:
1、MediaPlayer开始进行播放操作之前,必须先进入到 Prepared状态。
2、两种方法进入:Prepared方法: prepare() (synchronous)  ,  prepareAsync() (asynchronous)。准备完成,
   回调方法:setOnPreparedListener(android.media.MediaPlayer.OnPreparedListener).中的onPrepared()方法
3、必须注意:Preparing 状态很短暂,所有Preparing 状态下调用任何方法,结果不确定
4、Prepared方法必须在Initialized时候调用,否则抛出异常
5、Prepared状态下,就可以设置视频、音频的属性了:声音大小,屏幕宽度,【调用其他方法实现】



  • To start the playback, start() must be called. After start() returns successfully, the MediaPlayer object is in the Started state. isPlaying() can be called to test whether the MediaPlayer object is in the Started state.
    • While in the Started state, the internal player engine calls a user supplied OnBufferingUpdateListener.onBufferingUpdate() callback method if a OnBufferingUpdateListener has been registered beforehand via setOnBufferingUpdateListener(OnBufferingUpdateListener). This callback allows applications to keep track of the buffering status while streaming audio/video.
    • Calling start() has not effect on a MediaPlayer object that is already in the Started state.
  • Playback can be paused and stopped, and the current playback position can be adjusted. Playback can be paused via pause(). When the call to pause() returns, the MediaPlayer object enters the Paused state. Note that the transition from the Started state to the Paused state and vice versa happens asynchronously in the player engine. It may take some time before the state is updated in calls to isPlaying(), and it can be a number of seconds in the case of streamed content.
    • Calling start() to resume playback for a paused MediaPlayer object, and the resumed playback position is the same as where it was paused. When the call to start()returns, the paused MediaPlayer object goes back to the Started state.
    • Calling pause() has no effect on a MediaPlayer object that is already in the Paused state.
  • Calling stop() stops playback and causes a MediaPlayer in the StartedPausedPrepared or PlaybackCompleted state to enter the Stopped state.
    • Once in the Stopped state, playback cannot be started until prepare() or prepareAsync() are called to set the MediaPlayer object to the Prepared state again.
    • Calling stop() has no effect on a MediaPlayer object that is already in the Stopped state.
关于:start( ):想要播放视频,音频,必须调用此方法。
1、调用 start( ) 后,进入 Started 状态:用 isPlaying( ) 判断是否是Started状态。
2、进入到Started状态,MediaPlayer  Engine会回调 OnBufferingUpdateListener.onBufferingUpdate() ,可以追踪缓存情况【但是需要先注册监听器】
3、Started状态下调用:start( ) 不起作用。

关于:暂停,停止
暂停:
1、pause( ) :调用后,MediaPlayer进入 Paused 状态。注意:Started 和 Paused 之间的状态转换(异步更新状态)需要不短的时间,尤其是网络资源视频可能需要几秒钟。影响isPlaying( ) 的判断。
2、Paused状态下:调用start( ) 可以恢复播放,播放进度不变。MediaPlayer进入到 Started 状态、
3、Paused状态下,调用  pause( )  不起作用。

停止:
1、调用stop( ) ,播放器从: StartedPausedPrepared or PlaybackCompleted状态进入到  Stopped 状态。
2、一旦处于Stoped 状态,播放器想要恢复,只有一种办法:调用 prepare() 和 prepareAsync(),进入到Prepared状态、
3、Stoped状态下调用 、stop() 没任何作用

注意: 
1、MediaPlayer多媒体文件采用:双缓存机制实现播放。
2、方法调用结束后,才会进入相应的状态:start( )执行完毕,播放器进入Started状态。

  • The playback position can be adjusted with a call to seekTo(int).
    • Although the asynchronuous seekTo(int) call returns right way, the actual seek operation may take a while to finish, especially for audio/video being streamed. When the actual seek operation completes, the internal player engine calls a user supplied OnSeekComplete.onSeekComplete() if an OnSeekCompleteListener has been registered beforehand via setOnSeekCompleteListener(OnSeekCompleteListener).
    • Please note that seekTo(int) can also be called in the other states, such as PreparedPaused and PlaybackCompleted state.
    • Furthermore, the actual current playback position can be retrieved with a call to getCurrentPosition(), which is helpful for applications such as a Music player that need to keep track of the playback progress.
  • When the playback reaches the end of stream, the playback completes.
    • If the looping mode was being set to truewith setLooping(boolean), the MediaPlayer object shall remain in the Started state.
    • If the looping mode was set to false , the player engine calls a user supplied callback method, OnCompletion.onCompletion(), if a OnCompletionListener is registered beforehand via setOnCompletionListener(OnCompletionListener). The invoke of the callback signals that the object is now in the PlaybackCompleted state.
    • While in the PlaybackCompleted state, calling start() can restart the playback from the beginning of the audio/video source.

调节播放位置:调用 seekTo(int)
1、seekTo() 是异步方法,马上就能 return,但是真正的 seek 操作需要一点时间才能完成,尤其是 Video/Audio 是 streamed 时候。
     seekTo真正完成时候,播放器Engine 会回调:OnSeekComplete.onSeekComplete() 
2、注意:seekTo()可以在好几个状态下调用: PreparedPaused and PlaybackCompleted state.
3、除此之外,想要做播放进度的显示和控制,那么就调用: getCurrentPosition()

播放结束:
1、设置循环模式: setLooping(boolean)为true,播放,结束了,播放器也会进入到 Started 状态
2、如果设置setLooping(boolean)为false,那么播放结束会回调:OnCompletion.onCompletion(),回调函数会设置状态为:PlaybackCompleted
3、PlaybackCompleted 状态下,调用 start(),播放器会重新开始播放器【应该是进入到 Started状态】


Callbacks

Applications may want to register for informational and error events in order to be informed of some internal state update and possible runtime errors during playback or streaming. Registration for these events is done by properly setting the appropriate listeners (via calls tosetOnPreparedListener(OnPreparedListener)setOnPreparedListener, setOnVideoSizeChangedListener(OnVideoSizeChangedListener)setOnVideoSizeChangedListener,setOnSeekCompleteListener(OnSeekCompleteListener)setOnSeekCompleteListener, setOnCompletionListener(OnCompletionListener)setOnCompletionListener,setOnBufferingUpdateListener(OnBufferingUpdateListener)setOnBufferingUpdateListener, setOnInfoListener(OnInfoListener)setOnInfoListener,setOnErrorListener(OnErrorListener)setOnErrorListener, etc). In order to receive the respective callback associated with these listeners, applications are required to create MediaPlayer objects on a thread with its own Looper running (main UI thread by default has a Looper running).

翻译:
可以设置的回调函数,如上面。可以直接在UI线程中添加监听器。

MediaPlayer总结:
1、注意状态的转换,多看状态转换图
2、方法的调用对状态有限制,否则抛异常
3、设置回调函数
4、注意和Activity,SurfaceView的生命周期结合
5、用SurfaceView显示播放内容的时候,SurfaceView实例化完成后,才能start( ),
     否则报错。可以为SurfaceView设置监听,监听创建和销毁
6、Error状态:调用 reset( )-------> idel 状态
     其他状态 -----------> End 状态 【单向的,不可逆】
7、实际的MediaPlayer需要考虑手机收到电话时候的状态。
8、注意MediaPlayer的资源释放。


剩下的API是方法介绍,方法调用与状态对应关系,详情见API