MediaPlayerpublic class MediaPlayer extends Object 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 {@link android.widget.VideoView}.
Please see Audio and Video
for additional help using MediaPlayer.
Topics covered here are:
- State Diagram
- Valid and Invalid States
- Permissions
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.
From this state diagram, one can see that a MediaPlayer object has the
following states:
|
Fields Summary |
---|
private static final String | TAG | private int | mNativeContext | private int | mListenerContext | private android.view.Surface | mSurface | private android.view.SurfaceHolder | mSurfaceHolder | private EventHandler | mEventHandler | private PowerManager.WakeLock | mWakeLock | private boolean | mScreenOnWhilePlaying | private boolean | mStayAwake | private static final int | MEDIA_NOP | private static final int | MEDIA_PREPARED | private static final int | MEDIA_PLAYBACK_COMPLETE | private static final int | MEDIA_BUFFERING_UPDATE | private static final int | MEDIA_SEEK_COMPLETE | private static final int | MEDIA_SET_VIDEO_SIZE | private static final int | MEDIA_ERROR | private static final int | MEDIA_INFO | private OnPreparedListener | mOnPreparedListener | private OnCompletionListener | mOnCompletionListener | private OnBufferingUpdateListener | mOnBufferingUpdateListener | private OnSeekCompleteListener | mOnSeekCompleteListener | private OnVideoSizeChangedListener | mOnVideoSizeChangedListener | public static final int | MEDIA_ERROR_UNKNOWNUnspecified media player error. | public static final int | MEDIA_ERROR_SERVER_DIEDMedia server died. In this case, the application must release the
MediaPlayer object and instantiate a new one. | public static final int | MEDIA_ERROR_NOT_VALID_FOR_PROGRESSIVE_PLAYBACKThe video is streamed and its container is not valid for progressive
playback i.e the video's index (e.g moov atom) is not at the start of the
file. | private OnErrorListener | mOnErrorListener | public static final int | MEDIA_INFO_UNKNOWNUnspecified media player info. | public static final int | MEDIA_INFO_VIDEO_TRACK_LAGGINGThe video is too complex for the decoder: it can't decode frames fast
enough. Possibly only the audio plays fine at this stage. | public static final int | MEDIA_INFO_BAD_INTERLEAVINGBad interleaving means that a media has been improperly interleaved or
not interleaved at all, e.g has all the video samples first then all the
audio ones. Video is playing but a lot of disk seeks may be happening. | public static final int | MEDIA_INFO_NOT_SEEKABLEThe media cannot be seeked (e.g live stream) | private OnInfoListener | mOnInfoListener |
Constructors Summary |
---|
public MediaPlayer()Default constructor. Consider using one of the create() methods for
synchronously instantiating a MediaPlayer from a Uri or resource.
When done with the MediaPlayer, you should call {@link #release()},
to free the resources. If not released, too many MediaPlayer instances may
result in an exception.
Looper looper;
if ((looper = Looper.myLooper()) != null) {
mEventHandler = new EventHandler(this, looper);
} else if ((looper = Looper.getMainLooper()) != null) {
mEventHandler = new EventHandler(this, looper);
} else {
mEventHandler = null;
}
/* Native setup requires a weak reference to our object.
* It's easier to create it here than in C++.
*/
native_setup(new WeakReference<MediaPlayer>(this));
|
Methods Summary |
---|
private native void | _pause()
| private native void | _release()
| private native void | _reset()
| private native void | _start()
| private native void | _stop()
| public static android.media.MediaPlayer | create(android.content.Context context, android.net.Uri uri)Convenience method to create a MediaPlayer for a given Uri.
On success, {@link #prepare()} will already have been called and must not be called again.
When done with the MediaPlayer, you should call {@link #release()},
to free the resources. If not released, too many MediaPlayer instances will
result in an exception.
return create (context, uri, null);
| public static android.media.MediaPlayer | create(android.content.Context context, android.net.Uri uri, android.view.SurfaceHolder holder)Convenience method to create a MediaPlayer for a given Uri.
On success, {@link #prepare()} will already have been called and must not be called again.
When done with the MediaPlayer, you should call {@link #release()},
to free the resources. If not released, too many MediaPlayer instances will
result in an exception.
try {
MediaPlayer mp = new MediaPlayer();
mp.setDataSource(context, uri);
if (holder != null) {
mp.setDisplay(holder);
}
mp.prepare();
return mp;
} catch (IOException ex) {
Log.d(TAG, "create failed:", ex);
// fall through
} catch (IllegalArgumentException ex) {
Log.d(TAG, "create failed:", ex);
// fall through
} catch (SecurityException ex) {
Log.d(TAG, "create failed:", ex);
// fall through
}
return null;
| public static android.media.MediaPlayer | create(android.content.Context context, int resid)Convenience method to create a MediaPlayer for a given resource id.
On success, {@link #prepare()} will already have been called and must not be called again.
When done with the MediaPlayer, you should call {@link #release()},
to free the resources. If not released, too many MediaPlayer instances will
result in an exception.
try {
AssetFileDescriptor afd = context.getResources().openRawResourceFd(resid);
if (afd == null) return null;
MediaPlayer mp = new MediaPlayer();
mp.setDataSource(afd.getFileDescriptor(), afd.getStartOffset(), afd.getLength());
afd.close();
mp.prepare();
return mp;
} catch (IOException ex) {
Log.d(TAG, "create failed:", ex);
// fall through
} catch (IllegalArgumentException ex) {
Log.d(TAG, "create failed:", ex);
// fall through
} catch (SecurityException ex) {
Log.d(TAG, "create failed:", ex);
// fall through
}
return null;
| protected void | finalize() native_finalize();
| public native int | getCurrentPosition()Gets the current playback position.
| public native int | getDuration()Gets the duration of the file.
| public native android.graphics.Bitmap | getFrameAt(int msec)Currently not implemented, returns null.
| public native int | getVideoHeight()Returns the height of the video.
| public native int | getVideoWidth()Returns the width of the video.
| public native boolean | isLooping()Checks whether the MediaPlayer is looping or non-looping.
| public native boolean | isPlaying()Checks whether the MediaPlayer is playing.
| private final native void | native_finalize()
| private final native void | native_setup(java.lang.Object mediaplayer_this)
| public void | pause()Pauses playback. Call start() to resume.
stayAwake(false);
_pause();
| private static void | postEventFromNative(java.lang.Object mediaplayer_ref, int what, int arg1, int arg2, java.lang.Object obj)Called from native code when an interesting event happens. This method
just uses the EventHandler system to post the event back to the main app thread.
We use a weak reference to the original MediaPlayer object so that the native
code is safe from the object disappearing from underneath it. (This is
the cookie passed to native_setup().)
MediaPlayer mp = (MediaPlayer)((WeakReference)mediaplayer_ref).get();
if (mp == null) {
return;
}
if (mp.mEventHandler != null) {
Message m = mp.mEventHandler.obtainMessage(what, arg1, arg2, obj);
mp.mEventHandler.sendMessage(m);
}
| public native void | prepare()Prepares the player for playback, synchronously.
After setting the datasource and the display surface, you need to either
call prepare() or prepareAsync(). For files, it is OK to call prepare(),
which blocks until MediaPlayer is ready for playback.
| public native void | prepareAsync()Prepares the player for playback, asynchronously.
After setting the datasource and the display surface, you need to either
call prepare() or prepareAsync(). For streams, you should call prepareAsync(),
which returns immediately, rather than blocking until enough data has been
buffered.
| public void | release()Releases resources associated with this MediaPlayer object.
It is considered good practice to call this method when you're
done using the MediaPlayer.
stayAwake(false);
updateSurfaceScreenOn();
mOnPreparedListener = null;
mOnBufferingUpdateListener = null;
mOnCompletionListener = null;
mOnSeekCompleteListener = null;
mOnErrorListener = null;
mOnInfoListener = null;
mOnVideoSizeChangedListener = null;
_release();
| public void | reset()Resets the MediaPlayer to its uninitialized state. After calling
this method, you will have to initialize it again by setting the
data source and calling prepare().
stayAwake(false);
_reset();
// make sure none of the listeners get called anymore
mEventHandler.removeCallbacksAndMessages(null);
| public native void | seekTo(int msec)Seeks to specified time position.
| public native void | setAudioStreamType(int streamtype)Sets the audio stream type for this MediaPlayer. See {@link AudioManager}
for a list of stream types.
| public void | setDataSource(android.content.Context context, android.net.Uri uri)Sets the data source as a content Uri.
String scheme = uri.getScheme();
if(scheme == null || scheme.equals("file")) {
setDataSource(uri.getPath());
return;
}
AssetFileDescriptor fd = null;
try {
ContentResolver resolver = context.getContentResolver();
fd = resolver.openAssetFileDescriptor(uri, "r");
if (fd == null) {
return;
}
// Note: using getDeclaredLength so that our behavior is the same
// as previous versions when the content provider is returning
// a full file.
if (fd.getDeclaredLength() < 0) {
setDataSource(fd.getFileDescriptor());
} else {
setDataSource(fd.getFileDescriptor(), fd.getStartOffset(), fd.getDeclaredLength());
}
return;
} catch (SecurityException ex) {
} catch (IOException ex) {
} finally {
if (fd != null) {
fd.close();
}
}
setDataSource(uri.toString());
return;
| public native void | setDataSource(java.lang.String path)Sets the data source (file-path or http/rtsp URL) to use.
| public void | setDataSource(java.io.FileDescriptor fd)Sets the data source (FileDescriptor) to use. It is the caller's responsibility
to close the file descriptor. It is safe to do so as soon as this call returns.
// intentionally less than LONG_MAX
setDataSource(fd, 0, 0x7ffffffffffffffL);
| public native void | setDataSource(java.io.FileDescriptor fd, long offset, long length)Sets the data source (FileDescriptor) to use. It is the caller's responsibility
to close the file descriptor. It is safe to do so as soon as this call returns.
| public void | setDisplay(android.view.SurfaceHolder sh)Sets the SurfaceHolder to use for displaying the video portion of the media.
This call is optional. Not calling it when playing back a video will
result in only the audio track being played.
mSurfaceHolder = sh;
mSurface = sh.getSurface();
updateSurfaceScreenOn();
| public native void | setLooping(boolean looping)Sets the player to be looping or non-looping.
| public void | setOnBufferingUpdateListener(android.media.MediaPlayer$OnBufferingUpdateListener listener)Register a callback to be invoked when the status of a network
stream's buffer has changed.
mOnBufferingUpdateListener = listener;
| public void | setOnCompletionListener(android.media.MediaPlayer$OnCompletionListener listener)Register a callback to be invoked when the end of a media source
has been reached during playback.
mOnCompletionListener = listener;
| public void | setOnErrorListener(android.media.MediaPlayer$OnErrorListener listener)Register a callback to be invoked when an error has happened
during an asynchronous operation.
mOnErrorListener = listener;
| public void | setOnInfoListener(android.media.MediaPlayer$OnInfoListener listener)Register a callback to be invoked when an info/warning is available.
mOnInfoListener = listener;
| public void | setOnPreparedListener(android.media.MediaPlayer$OnPreparedListener listener)Register a callback to be invoked when the media source is ready
for playback.
mOnPreparedListener = listener;
| public void | setOnSeekCompleteListener(android.media.MediaPlayer$OnSeekCompleteListener listener)Register a callback to be invoked when a seek operation has been
completed.
mOnSeekCompleteListener = listener;
| public void | setOnVideoSizeChangedListener(android.media.MediaPlayer$OnVideoSizeChangedListener listener)Register a callback to be invoked when the video size is
known or updated.
mOnVideoSizeChangedListener = listener;
| public void | setScreenOnWhilePlaying(boolean screenOn)Control whether we should use the attached SurfaceHolder to keep the
screen on while video playback is occurring. This is the preferred
method over {@link #setWakeMode} where possible, since it doesn't
require that the application have permission for low-level wake lock
access.
if (mScreenOnWhilePlaying != screenOn) {
mScreenOnWhilePlaying = screenOn;
updateSurfaceScreenOn();
}
| public native void | setVolume(float leftVolume, float rightVolume)Sets the volume on this player.
This API is recommended for balancing the output of audio streams
within an application. Unless you are writing an application to
control user settings, this API should be used in preference to
{@link AudioManager#setStreamVolume(int, int, int)} which sets the volume of ALL streams of
a particular type. Note that the passed volume values are raw scalars.
UI controls should be scaled logarithmically.
| public void | setWakeMode(android.content.Context context, int mode)Set the low-level power management behavior for this MediaPlayer. This
can be used when the MediaPlayer is not playing through a SurfaceHolder
set with {@link #setDisplay(SurfaceHolder)} and thus can use the
high-level {@link #setScreenOnWhilePlaying(boolean)} feature.
This function has the MediaPlayer access the low-level power manager
service to control the device's power usage while playing is occurring.
The parameter is a combination of {@link android.os.PowerManager} wake flags.
Use of this method requires {@link android.Manifest.permission#WAKE_LOCK}
permission.
By default, no attempt is made to keep the device awake during playback.
boolean washeld = false;
if (mWakeLock != null) {
if (mWakeLock.isHeld()) {
washeld = true;
mWakeLock.release();
}
mWakeLock = null;
}
PowerManager pm = (PowerManager)context.getSystemService(Context.POWER_SERVICE);
mWakeLock = pm.newWakeLock(mode|PowerManager.ON_AFTER_RELEASE, MediaPlayer.class.getName());
mWakeLock.setReferenceCounted(false);
if (washeld) {
mWakeLock.acquire();
}
| public void | start()Starts or resumes playback. If playback had previously been paused,
playback will continue from where it was paused. If playback had
been stopped, or never started before, playback will start at the
beginning.
stayAwake(true);
_start();
| private void | stayAwake(boolean awake)
if (mWakeLock != null) {
if (awake && !mWakeLock.isHeld()) {
mWakeLock.acquire();
} else if (!awake && mWakeLock.isHeld()) {
mWakeLock.release();
}
}
mStayAwake = awake;
updateSurfaceScreenOn();
| public void | stop()Stops playback after playback has been stopped or paused.
stayAwake(false);
_stop();
| private void | updateSurfaceScreenOn()
if (mSurfaceHolder != null) {
mSurfaceHolder.setKeepScreenOn(mScreenOnWhilePlaying && mStayAwake);
}
|
|