Methods Summary |
---|
public void | addSubtitleSource(java.io.InputStream is, android.media.MediaFormat format)Adds an external subtitle source file (from the provided input stream.)
Note that a single external subtitle source may contain multiple or no
supported tracks in it. If the source contained at least one track in
it, one will receive an {@link MediaPlayer#MEDIA_INFO_METADATA_UPDATE}
info message. Otherwise, if reading the source takes excessive time,
one will receive a {@link MediaPlayer#MEDIA_INFO_SUBTITLE_TIMED_OUT}
message. If the source contained no supported track (including an empty
source file or null input stream), one will receive a {@link
MediaPlayer#MEDIA_INFO_UNSUPPORTED_SUBTITLE} message. One can find the
total number of available tracks using {@link MediaPlayer#getTrackInfo()}
to see what additional tracks become available after this method call.
if (mMediaPlayer == null) {
mPendingSubtitleTracks.add(Pair.create(is, format));
} else {
try {
mMediaPlayer.addSubtitleSource(is, format);
} catch (IllegalStateException e) {
mInfoListener.onInfo(
mMediaPlayer, MediaPlayer.MEDIA_INFO_UNSUPPORTED_SUBTITLE, 0);
}
}
|
private void | attachMediaController()
if (mMediaPlayer != null && mMediaController != null) {
mMediaController.setMediaPlayer(this);
View anchorView = this.getParent() instanceof View ?
(View)this.getParent() : this;
mMediaController.setAnchorView(anchorView);
mMediaController.setEnabled(isInPlaybackState());
}
|
public boolean | canPause()
return mCanPause;
|
public boolean | canSeekBackward()
return mCanSeekBack;
|
public boolean | canSeekForward()
return mCanSeekForward;
|
public void | draw(android.graphics.Canvas canvas)
super.draw(canvas);
if (mSubtitleWidget != null) {
final int saveCount = canvas.save();
canvas.translate(getPaddingLeft(), getPaddingTop());
mSubtitleWidget.draw(canvas);
canvas.restoreToCount(saveCount);
}
|
public int | getAudioSessionId()
if (mAudioSession == 0) {
MediaPlayer foo = new MediaPlayer();
mAudioSession = foo.getAudioSessionId();
foo.release();
}
return mAudioSession;
|
public int | getBufferPercentage()
if (mMediaPlayer != null) {
return mCurrentBufferPercentage;
}
return 0;
|
public int | getCurrentPosition()
if (isInPlaybackState()) {
return mMediaPlayer.getCurrentPosition();
}
return 0;
|
public int | getDuration()
if (isInPlaybackState()) {
return mMediaPlayer.getDuration();
}
return -1;
|
public android.os.Looper | getSubtitleLooper()
return Looper.getMainLooper();
|
private void | initVideoView()
mVideoWidth = 0;
mVideoHeight = 0;
getHolder().addCallback(mSHCallback);
getHolder().setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
setFocusable(true);
setFocusableInTouchMode(true);
requestFocus();
mPendingSubtitleTracks = new Vector<Pair<InputStream, MediaFormat>>();
mCurrentState = STATE_IDLE;
mTargetState = STATE_IDLE;
|
private boolean | isInPlaybackState()
return (mMediaPlayer != null &&
mCurrentState != STATE_ERROR &&
mCurrentState != STATE_IDLE &&
mCurrentState != STATE_PREPARING);
|
public boolean | isPlaying()
return isInPlaybackState() && mMediaPlayer.isPlaying();
|
private void | measureAndLayoutSubtitleWidget()Forces a measurement and layout pass for all overlaid views.
final int width = getWidth() - getPaddingLeft() - getPaddingRight();
final int height = getHeight() - getPaddingTop() - getPaddingBottom();
mSubtitleWidget.setSize(width, height);
|
protected void | onAttachedToWindow()
super.onAttachedToWindow();
if (mSubtitleWidget != null) {
mSubtitleWidget.onAttachedToWindow();
}
|
protected void | onDetachedFromWindow()
super.onDetachedFromWindow();
if (mSubtitleWidget != null) {
mSubtitleWidget.onDetachedFromWindow();
}
|
public void | onInitializeAccessibilityEvent(android.view.accessibility.AccessibilityEvent event)
super.onInitializeAccessibilityEvent(event);
event.setClassName(VideoView.class.getName());
|
public void | onInitializeAccessibilityNodeInfo(android.view.accessibility.AccessibilityNodeInfo info)
super.onInitializeAccessibilityNodeInfo(info);
info.setClassName(VideoView.class.getName());
|
public boolean | onKeyDown(int keyCode, android.view.KeyEvent event)
boolean isKeyCodeSupported = keyCode != KeyEvent.KEYCODE_BACK &&
keyCode != KeyEvent.KEYCODE_VOLUME_UP &&
keyCode != KeyEvent.KEYCODE_VOLUME_DOWN &&
keyCode != KeyEvent.KEYCODE_VOLUME_MUTE &&
keyCode != KeyEvent.KEYCODE_MENU &&
keyCode != KeyEvent.KEYCODE_CALL &&
keyCode != KeyEvent.KEYCODE_ENDCALL;
if (isInPlaybackState() && isKeyCodeSupported && mMediaController != null) {
if (keyCode == KeyEvent.KEYCODE_HEADSETHOOK ||
keyCode == KeyEvent.KEYCODE_MEDIA_PLAY_PAUSE) {
if (mMediaPlayer.isPlaying()) {
pause();
mMediaController.show();
} else {
start();
mMediaController.hide();
}
return true;
} else if (keyCode == KeyEvent.KEYCODE_MEDIA_PLAY) {
if (!mMediaPlayer.isPlaying()) {
start();
mMediaController.hide();
}
return true;
} else if (keyCode == KeyEvent.KEYCODE_MEDIA_STOP
|| keyCode == KeyEvent.KEYCODE_MEDIA_PAUSE) {
if (mMediaPlayer.isPlaying()) {
pause();
mMediaController.show();
}
return true;
} else {
toggleMediaControlsVisiblity();
}
}
return super.onKeyDown(keyCode, event);
|
protected void | onLayout(boolean changed, int left, int top, int right, int bottom)
super.onLayout(changed, left, top, right, bottom);
if (mSubtitleWidget != null) {
measureAndLayoutSubtitleWidget();
}
|
protected void | onMeasure(int widthMeasureSpec, int heightMeasureSpec)
//Log.i("@@@@", "onMeasure(" + MeasureSpec.toString(widthMeasureSpec) + ", "
// + MeasureSpec.toString(heightMeasureSpec) + ")");
int width = getDefaultSize(mVideoWidth, widthMeasureSpec);
int height = getDefaultSize(mVideoHeight, heightMeasureSpec);
if (mVideoWidth > 0 && mVideoHeight > 0) {
int widthSpecMode = MeasureSpec.getMode(widthMeasureSpec);
int widthSpecSize = MeasureSpec.getSize(widthMeasureSpec);
int heightSpecMode = MeasureSpec.getMode(heightMeasureSpec);
int heightSpecSize = MeasureSpec.getSize(heightMeasureSpec);
if (widthSpecMode == MeasureSpec.EXACTLY && heightSpecMode == MeasureSpec.EXACTLY) {
// the size is fixed
width = widthSpecSize;
height = heightSpecSize;
// for compatibility, we adjust size based on aspect ratio
if ( mVideoWidth * height < width * mVideoHeight ) {
//Log.i("@@@", "image too wide, correcting");
width = height * mVideoWidth / mVideoHeight;
} else if ( mVideoWidth * height > width * mVideoHeight ) {
//Log.i("@@@", "image too tall, correcting");
height = width * mVideoHeight / mVideoWidth;
}
} else if (widthSpecMode == MeasureSpec.EXACTLY) {
// only the width is fixed, adjust the height to match aspect ratio if possible
width = widthSpecSize;
height = width * mVideoHeight / mVideoWidth;
if (heightSpecMode == MeasureSpec.AT_MOST && height > heightSpecSize) {
// couldn't match aspect ratio within the constraints
height = heightSpecSize;
}
} else if (heightSpecMode == MeasureSpec.EXACTLY) {
// only the height is fixed, adjust the width to match aspect ratio if possible
height = heightSpecSize;
width = height * mVideoWidth / mVideoHeight;
if (widthSpecMode == MeasureSpec.AT_MOST && width > widthSpecSize) {
// couldn't match aspect ratio within the constraints
width = widthSpecSize;
}
} else {
// neither the width nor the height are fixed, try to use actual video size
width = mVideoWidth;
height = mVideoHeight;
if (heightSpecMode == MeasureSpec.AT_MOST && height > heightSpecSize) {
// too tall, decrease both width and height
height = heightSpecSize;
width = height * mVideoWidth / mVideoHeight;
}
if (widthSpecMode == MeasureSpec.AT_MOST && width > widthSpecSize) {
// too wide, decrease both width and height
width = widthSpecSize;
height = width * mVideoHeight / mVideoWidth;
}
}
} else {
// no size yet, just adopt the given spec sizes
}
setMeasuredDimension(width, height);
|
public boolean | onTouchEvent(android.view.MotionEvent ev)
if (isInPlaybackState() && mMediaController != null) {
toggleMediaControlsVisiblity();
}
return false;
|
public boolean | onTrackballEvent(android.view.MotionEvent ev)
if (isInPlaybackState() && mMediaController != null) {
toggleMediaControlsVisiblity();
}
return false;
|
private void | openVideo()
if (mUri == null || mSurfaceHolder == null) {
// not ready for playback just yet, will try again later
return;
}
AudioManager am = (AudioManager) mContext.getSystemService(Context.AUDIO_SERVICE);
am.requestAudioFocus(null, AudioManager.STREAM_MUSIC, AudioManager.AUDIOFOCUS_GAIN);
// we shouldn't clear the target state, because somebody might have
// called start() previously
release(false);
try {
mMediaPlayer = new MediaPlayer();
// TODO: create SubtitleController in MediaPlayer, but we need
// a context for the subtitle renderers
final Context context = getContext();
final SubtitleController controller = new SubtitleController(
context, mMediaPlayer.getMediaTimeProvider(), mMediaPlayer);
controller.registerRenderer(new WebVttRenderer(context));
controller.registerRenderer(new TtmlRenderer(context));
controller.registerRenderer(new ClosedCaptionRenderer(context));
mMediaPlayer.setSubtitleAnchor(controller, this);
if (mAudioSession != 0) {
mMediaPlayer.setAudioSessionId(mAudioSession);
} else {
mAudioSession = mMediaPlayer.getAudioSessionId();
}
mMediaPlayer.setOnPreparedListener(mPreparedListener);
mMediaPlayer.setOnVideoSizeChangedListener(mSizeChangedListener);
mMediaPlayer.setOnCompletionListener(mCompletionListener);
mMediaPlayer.setOnErrorListener(mErrorListener);
mMediaPlayer.setOnInfoListener(mInfoListener);
mMediaPlayer.setOnBufferingUpdateListener(mBufferingUpdateListener);
mCurrentBufferPercentage = 0;
mMediaPlayer.setDataSource(mContext, mUri, mHeaders);
mMediaPlayer.setDisplay(mSurfaceHolder);
mMediaPlayer.setAudioStreamType(AudioManager.STREAM_MUSIC);
mMediaPlayer.setScreenOnWhilePlaying(true);
mMediaPlayer.prepareAsync();
for (Pair<InputStream, MediaFormat> pending: mPendingSubtitleTracks) {
try {
mMediaPlayer.addSubtitleSource(pending.first, pending.second);
} catch (IllegalStateException e) {
mInfoListener.onInfo(
mMediaPlayer, MediaPlayer.MEDIA_INFO_UNSUPPORTED_SUBTITLE, 0);
}
}
// we don't set the target state here either, but preserve the
// target state that was there before.
mCurrentState = STATE_PREPARING;
attachMediaController();
} catch (IOException ex) {
Log.w(TAG, "Unable to open content: " + mUri, ex);
mCurrentState = STATE_ERROR;
mTargetState = STATE_ERROR;
mErrorListener.onError(mMediaPlayer, MediaPlayer.MEDIA_ERROR_UNKNOWN, 0);
return;
} catch (IllegalArgumentException ex) {
Log.w(TAG, "Unable to open content: " + mUri, ex);
mCurrentState = STATE_ERROR;
mTargetState = STATE_ERROR;
mErrorListener.onError(mMediaPlayer, MediaPlayer.MEDIA_ERROR_UNKNOWN, 0);
return;
} finally {
mPendingSubtitleTracks.clear();
}
|
public void | pause()
if (isInPlaybackState()) {
if (mMediaPlayer.isPlaying()) {
mMediaPlayer.pause();
mCurrentState = STATE_PAUSED;
}
}
mTargetState = STATE_PAUSED;
|
private void | release(boolean cleartargetstate)
/*
* release the media player in any state
*/
if (mMediaPlayer != null) {
mMediaPlayer.reset();
mMediaPlayer.release();
mMediaPlayer = null;
mPendingSubtitleTracks.clear();
mCurrentState = STATE_IDLE;
if (cleartargetstate) {
mTargetState = STATE_IDLE;
}
}
|
public int | resolveAdjustedSize(int desiredSize, int measureSpec)
return getDefaultSize(desiredSize, measureSpec);
|
public void | resume()
openVideo();
|
public void | seekTo(int msec)
if (isInPlaybackState()) {
mMediaPlayer.seekTo(msec);
mSeekWhenPrepared = 0;
} else {
mSeekWhenPrepared = msec;
}
|
public void | setMediaController(MediaController controller)
if (mMediaController != null) {
mMediaController.hide();
}
mMediaController = controller;
attachMediaController();
|
public void | setOnCompletionListener(android.media.MediaPlayer.OnCompletionListener l)Register a callback to be invoked when the end of a media file
has been reached during playback.
mOnCompletionListener = l;
|
public void | setOnErrorListener(android.media.MediaPlayer.OnErrorListener l)Register a callback to be invoked when an error occurs
during playback or setup. If no listener is specified,
or if the listener returned false, VideoView will inform
the user of any errors.
mOnErrorListener = l;
|
public void | setOnInfoListener(android.media.MediaPlayer.OnInfoListener l)Register a callback to be invoked when an informational event
occurs during playback or setup.
mOnInfoListener = l;
|
public void | setOnPreparedListener(MediaPlayer.OnPreparedListener l)Register a callback to be invoked when the media file
is loaded and ready to go.
mOnPreparedListener = l;
|
public void | setSubtitleWidget(android.media.SubtitleTrack.RenderingWidget subtitleWidget)
if (mSubtitleWidget == subtitleWidget) {
return;
}
final boolean attachedToWindow = isAttachedToWindow();
if (mSubtitleWidget != null) {
if (attachedToWindow) {
mSubtitleWidget.onDetachedFromWindow();
}
mSubtitleWidget.setOnChangedListener(null);
}
mSubtitleWidget = subtitleWidget;
if (subtitleWidget != null) {
if (mSubtitlesChangedListener == null) {
mSubtitlesChangedListener = new RenderingWidget.OnChangedListener() {
@Override
public void onChanged(RenderingWidget renderingWidget) {
invalidate();
}
};
}
setWillNotDraw(false);
subtitleWidget.setOnChangedListener(mSubtitlesChangedListener);
if (attachedToWindow) {
subtitleWidget.onAttachedToWindow();
requestLayout();
}
} else {
setWillNotDraw(true);
}
invalidate();
|
public void | setVideoPath(java.lang.String path)Sets video path.
setVideoURI(Uri.parse(path));
|
public void | setVideoURI(android.net.Uri uri)Sets video URI.
setVideoURI(uri, null);
|
public void | setVideoURI(android.net.Uri uri, java.util.Map headers)Sets video URI using specific headers.
mUri = uri;
mHeaders = headers;
mSeekWhenPrepared = 0;
openVideo();
requestLayout();
invalidate();
|
public void | start()
if (isInPlaybackState()) {
mMediaPlayer.start();
mCurrentState = STATE_PLAYING;
}
mTargetState = STATE_PLAYING;
|
public void | stopPlayback()
if (mMediaPlayer != null) {
mMediaPlayer.stop();
mMediaPlayer.release();
mMediaPlayer = null;
mCurrentState = STATE_IDLE;
mTargetState = STATE_IDLE;
}
|
public void | suspend()
release(false);
|
private void | toggleMediaControlsVisiblity()
if (mMediaController.isShowing()) {
mMediaController.hide();
} else {
mMediaController.show();
}
|