From d92e59985ca015c4a4662372f854f6a8bd75522d Mon Sep 17 00:00:00 2001
From: Wei Jia Topics covered here are:
* For more information about how to use MediaPlayer2, read the
- * Media Playback developer guide. 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
- * MediaPlayer2 object driven by the supported playback control operations.
- * The ovals represent the states a MediaPlayer2 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. The playback control of audio/video files is managed as a state machine.
- *
*
- * Developer Guides
- * State Diagram
+ * Player states
*
- * 
The MediaPlayer2 object has five states:
+ *{@link #PLAYER_STATE_IDLE}: MediaPlayer2 is in the Idle + * state after you create it using + * {@link #create()}, or after calling {@link #reset()}.
* - *
While in this state, you should call
+ * {@link #setDataSource(DataSourceDesc2) setDataSource()}. It is a good
+ * programming practice to register an {@link EventCallback#onCallCompleted onCallCompleted}
+ * callback and watch for {@link #CALL_STATUS_BAD_VALUE} and
+ * {@link #CALL_STATUS_ERROR_IO}, which might be caused by setDataSource.
+ *
Calling {@link #prepare()} transfers a MediaPlayer2 object to + * the Prepared state. Note + * that {@link #prepare()} is asynchronous. When the preparation completes, + * if you register an {@link EventCallback#onInfo onInfo} callback, + * the player executes the callback + * with {@link #MEDIA_INFO_PREPARED} and transitions to the + * Prepared state.
+ *The player plays the data source while in this state. + * If you register an {@link EventCallback#onInfo onInfo} callback, + * the player regularly executes the callback with + * {@link #MEDIA_INFO_BUFFERING_UPDATE}. + * This allows applications to keep track of the buffering status + * while streaming audio/video.
+ * + *When the playback reaches the end of stream, the behavior depends on whether or + * not you've enabled looping by calling {@link #loopCurrent(boolean) loopCurrent}:
+ *false, the player will transfer
+ * to the Paused state. If you registered an {@link EventCallback#onInfo
+ * onInfo} callback
+ * the player calls the callback with {@link #MEDIA_INFO_DATA_SOURCE_END} and enters
+ * the Paused state.
+ * true,
+ * the MediaPlayer2 object remains in the Playing state and replays its
+ * data source from the beginning.In general, playback might fail due to various + * reasons such as unsupported audio/video format, poorly interleaved + * audio/video, resolution too high, streaming timeout, and others. + * In addition, due to programming errors, a playback + * control operation might be performed from an invalid state. + * In these cases the player transitions to the Error state.
+ * + *If you register an {@link EventCallback#onError onError}} + * callback, + * the callback will be performed when entering the state. When programming errors happen, + * such as calling {@link #prepare() prepare} and + * {@link #setDataSource(DataSourceDesc) setDataSource} methods + * from an invalid state, the callback is called with + * {@link #CALL_STATUS_INVALID_OPERATION}. The MediaPlayer2 object enters the + * Error state whether or not a callback exists.
+ * + *To recover from an error and reuse a MediaPlayer2 object that is in the + * Error state, + * call {@link #reset() reset}. The object will return to the Idle + * state and all state information will be lost.
+ *You should follow these best practices when coding an app that uses MediaPlayer2:
* - *From this state diagram, one can see that a MediaPlayer2 object has the - * following states:
*create or
- * after {@link #reset()} is called, it is in the Idle state; and after
- * {@link #close()} is called, it is in the End state. Between these
- * two states is the life cycle of the MediaPlayer2 object.
- * new is in the
- * Idle state.
- * IllegalArgumentException
- * and IOException that may be thrown from
- * setDataSource.The only methods you safely call from the Error state are + * {@link #close() close}, + * {@link #reset() reset}, + * {@link #notifyWhenCommandLabelReached notifyWhenCommandLabelReached}, + * {@link #clearPendingCommands() clearPendingCommands}, + * {@link #setEventCallback setEventCallback}, + * {@link #clearEventCallback() clearEventCallback} + * and {@link #getState() getState}. + * Any other methods might throw an exception, return meaningless data, or invoke a + * {@link EventCallback#onCallCompleted onCallCompleted} with an error code.
+ * + *Most methods can be called from any non-Error state. They will either perform their work or + * silently have no effect. The following table lists the methods that will invoke a + * {@link EventCallback#onCallCompleted onCallCompleted} with an error code + * or throw an exception when they are called from the associated invalid states.
* *| Method Name | - *Valid Sates | - *Invalid States | - *Comments |
| attachAuxEffect | - *{Initialized, Prepared, Started, Paused, Stopped, PlaybackCompleted} | - *{Idle, Error} | - *This method must be called after setDataSource. - * Calling it does not change the object state. |
| getAudioSessionId | - *any | - *{} | - *This method can be called in any state and calling it does not change - * the object state. |
| getCurrentPosition | - *{Idle, Initialized, Prepared, Started, Paused, Stopped, - * PlaybackCompleted} | - *{Error} | - *Successful invoke of this method in a valid state does not change the - * state. Calling this method in an invalid state transfers the object - * to the Error state. |
| getDuration | - *{Prepared, Started, Paused, Stopped, PlaybackCompleted} | - *{Idle, Initialized, Error} | - *Successful invoke of this method in a valid state does not change the - * state. Calling this method in an invalid state transfers the object - * to the Error state. |
| getVideoHeight | - *{Idle, Initialized, Prepared, Started, Paused, Stopped, - * PlaybackCompleted} | - *{Error} | - *Successful invoke of this method in a valid state does not change the - * state. Calling this method in an invalid state transfers the object - * to the Error state. |
| getVideoWidth | - *{Idle, Initialized, Prepared, Started, Paused, Stopped, - * PlaybackCompleted} | - *{Error} | - *Successful invoke of this method in a valid state does not change - * the state. Calling this method in an invalid state transfers the - * object to the Error state. |
| getPlayerState | - *{Idle, Initialized, Prepared, Started, Paused, Stopped, - * PlaybackCompleted} | - *{Error} | - *Successful invoke of this method in a valid state does not change - * the state. Calling this method in an invalid state transfers the - * object to the Error state. |
| pause | - *{Started, Paused, PlaybackCompleted} | - *{Idle, Initialized, Prepared, Stopped, Error} | - *Successful invoke of this method in a valid state transfers the - * object to the Paused state. Calling this method in an - * invalid state transfers the object to the Error state. |
| prepare | - *{Initialized, Stopped} | - *{Idle, Prepared, Started, Paused, PlaybackCompleted, Error} | - *Successful invoke of this method in a valid state transfers the - * object to the Preparing state. Calling this method in an - * invalid state throws an IllegalStateException. |
| release | - *any | - *{} | - *After {@link #close()}, the object is no longer available. |
| reset | - *{Idle, Initialized, Prepared, Started, Paused, Stopped, - * PlaybackCompleted, Error} | - *{} | - *After {@link #reset()}, the object is like being just created. |
| seekTo | - *{Prepared, Started, Paused, PlaybackCompleted} | - *{Idle, Initialized, Stopped, Error} | - *Successful invoke of this method in a valid state does not change - * the state. Calling this method in an invalid state transfers the - * object to the Error state. |
| setAudioAttributes | - *{Idle, Initialized, Stopped, Prepared, Started, Paused, - * PlaybackCompleted} | - *{Error} | - *Successful invoke of this method does not change the state. In order for the - * target audio attributes type to become effective, this method must be called before - * prepare(). |
| setAudioSessionId | - *{Idle} | - *{Initialized, Prepared, Started, Paused, Stopped, PlaybackCompleted, - * Error} | - *This method must be called in idle state as the audio session ID must be known before - * calling setDataSource. Calling it does not change the object - * state. |
| setAudioStreamType (deprecated) | - *{Idle, Initialized, Stopped, Prepared, Started, Paused, - * PlaybackCompleted} | - *{Error} | - *Successful invoke of this method does not change the state. In order for the - * target audio stream type to become effective, this method must be called before - * prepare(). |
| setAuxEffectSendLevel | - *any | - *{} | - *Calling this method does not change the object state. |
| setDataSource | - *{Idle} | - *{Initialized, Prepared, Started, Paused, Stopped, PlaybackCompleted, - * Error} | - *Successful invoke of this method in a valid state transfers the - * object to the Initialized state. Calling this method in an - * invalid state throws an IllegalStateException. |
| setDisplay | - *any | - *{} | - *This method can be called in any state and calling it does not change - * the object state. |
| setSurface | - *any | - *{} | - *This method can be called in any state and calling it does not change - * the object state. |
| loopCurrent | - *{Idle, Initialized, Stopped, Prepared, Started, Paused, - * PlaybackCompleted} | - *{Error} | - *Successful invoke of this method in a valid state does not change - * the state. Calling this method in an - * invalid state transfers the object to the Error state. |
| isLooping | - *any | - *{} | - *This method can be called in any state and calling it does not change - * the object state. |
| setDrmEventCallback | - *any | - *{} | - *This method can be called in any state and calling it does not change - * the object state. |
| setEventCallback | - *any | - *{} | - *This method can be called in any state and calling it does not change - * the object state. |
| setPlaybackParams | - *{Initialized, Prepared, Started, Paused, PlaybackCompleted, Error} | - *{Idle, Stopped} | - *This method will change state in some cases, depending on when it's called. - * |
| setPlayerVolume | - *{Idle, Initialized, Stopped, Prepared, Started, Paused, - * PlaybackCompleted} | - *{Error} | - *Successful invoke of this method does not change the state. - * |
| play | - *{Prepared, Started, Paused, PlaybackCompleted} | - *{Idle, Initialized, Stopped, Error} | - *Successful invoke of this method in a valid state transfers the - * object to the Started state. Calling this method in an - * invalid state transfers the object to the Error state. |
| stop | - *{Prepared, Started, Stopped, Paused, PlaybackCompleted} | - *{Idle, Initialized, Error} | - *Successful invoke of this method in a valid state transfers the - * object to the Stopped state. Calling this method in an - * invalid state transfers the object to the Error state. |
| getTrackInfo | - *{Prepared, Started, Stopped, Paused, PlaybackCompleted} | - *{Idle, Initialized, Error} | - *Successful invoke of this method does not change the state. |
| selectTrack | - *{Prepared, Started, Stopped, Paused, PlaybackCompleted} | - *{Idle, Initialized, Error} | - *Successful invoke of this method does not change the state. |
| deselectTrack | - *{Prepared, Started, Stopped, Paused, PlaybackCompleted} | - *{Idle, Initialized, Error} | - *Successful invoke of this method does not change the state. |
| Method Name | + *Invalid States | ||
|---|---|---|---|
| setDataSource | {Prepared, Paused, Playing} | ||
| prepare | {Prepared, Paused, Playing} | ||
| play | {Idle} | ||
| pause | {Idle} | ||
| seekTo | {Idle} | ||
| getCurrentPosition | {Idle} | ||
| getDuration | {Idle} | ||
| getBufferedPosition | {Idle} | ||
| getTrackInfo | {Idle} | ||
| getSelectedTrack | {Idle} | ||
| selectTrack | {Idle} | ||
| deselectTrack | {Idle} |
One may need to declare a corresponding WAKE_LOCK permission {@link - * android.R.styleable#AndroidManifestUsesPermission <uses-permission>} - * element. - * + *
This class requires the {@link android.Manifest.permission#INTERNET} permission * when used with network-based content. * - * - *
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 - * to - * {@link #setEventCallback(Executor, EventCallback)}, - * {@link #setDrmEventCallback(Executor, DrmEventCallback)}). - * In order to receive the respective callback - * associated with these listeners, applications are required to create - * MediaPlayer2 objects on a thread with its own Looper running (main UI - * thread by default has a Looper running). + *
Many errors do not result in a transition to the Error state. + * It is good programming practice to register callback listeners using + * {@link #setEventCallback(Executor, EventCallback) setEventCallback} and + * {@link #setDrmEventCallback(Executor, DrmEventCallback) setDrmEventCallback}). + * You can receive a callback at any time and from any state.
* + *If it's important for your app to respond to state changes (for instance, to update the
+ * controls on a transport UI), you should register an
+ * {@link EventCallback#onCallCompleted onCallCompleted} and
+ * detect state change commands by testing the what parameter for a callback from one
+ * of the state transition methods: {@link #CALL_COMPLETED_PREPARE}, {@link #CALL_COMPLETED_PLAY},
+ * and {@link #CALL_COMPLETED_PAUSE}.
+ * Then check the status parameter. The value {@link #CALL_STATUS_NO_ERROR} indicates a
+ * successful transition. Any other value will be an error. Call {@link #getState()} to
+ * determine the current state.