Created
October 6, 2015 21:27
-
-
Save barbosa-renan/e49c482436efddd4ecd1 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package com.prologica.wizardplayer; | |
import java.io.IOException; | |
import com.prologica.wizardplayer.common.TagNames; | |
import com.prologica.wizardplayer.common.Utils; | |
import android.content.Context; | |
import android.graphics.SurfaceTexture; | |
import android.media.AudioManager; | |
import android.media.MediaPlayer; | |
import android.media.MediaPlayer.OnCompletionListener; | |
import android.media.MediaPlayer.OnErrorListener; | |
import android.media.MediaPlayer.OnInfoListener; | |
import android.media.MediaPlayer.OnPreparedListener; | |
import android.media.MediaPlayer.OnSeekCompleteListener; | |
import android.media.MediaPlayer.OnVideoSizeChangedListener; | |
import android.os.PowerManager; | |
import android.util.AttributeSet; | |
import android.view.KeyEvent; | |
import android.view.Surface; | |
import android.view.TextureView; | |
import android.view.accessibility.AccessibilityEvent; | |
import android.view.accessibility.AccessibilityNodeInfo; | |
/** | |
* Displays a video file. | |
*/ | |
public class VideoPlayer extends TextureView | |
{ | |
// constants | |
private static final int STATE_ERROR = -1; | |
private static final int STATE_IDLE = 0; | |
private static final int STATE_PREPARING = 1; | |
private static final int STATE_PREPARED = 2; | |
private static final int STATE_PLAYING = 3; | |
private static final int STATE_PAUSED = 4; | |
private static final int STATE_PLAYBACK_COMPLETED = 5; | |
private static final int STATE_STOPED = 6; | |
// variables | |
private static SurfaceTexture sf; | |
private static Surface sf1; | |
private static int mVideoWidth; | |
private static int mVideoHeight; | |
private static int mCurrentState = STATE_IDLE; | |
private static MediaPlayer mMediaPlayer; | |
private static String path; | |
private OnCompletionListener mOnCompletionListener; | |
private OnPreparedListener mOnPreparedListener; | |
private OnErrorListener mOnErrorListener; | |
private OnInfoListener mOnInfoListener; | |
private static int mCurrentBufferPercentage; | |
private static int mSeekWhenPrepared; | |
private PlayPauseListener mListener; | |
private int skip = 5000, skip1 = 5000; | |
double startTime, finalTime; | |
private Context _context; | |
public VideoPlayer(Context context) | |
{ | |
super(context); | |
_context = context; | |
} | |
public VideoPlayer(Context context, AttributeSet attrs) | |
{ | |
this(context, attrs, 0); | |
initVideoView(context); | |
} | |
public VideoPlayer(Context context, AttributeSet attrs, int defStyle) | |
{ | |
super(context, attrs, defStyle); | |
} | |
OnVideoSizeChangedListener mSizeChangedListener = new OnVideoSizeChangedListener() | |
{ | |
public void onVideoSizeChanged(MediaPlayer mp, int width, int height) | |
{ | |
mVideoWidth = mp.getVideoWidth(); | |
mVideoHeight = mp.getVideoHeight(); | |
requestLayout(); | |
} | |
}; | |
OnPreparedListener mPreparedListener = new OnPreparedListener() | |
{ | |
public void onPrepared(MediaPlayer mp) | |
{ | |
mCurrentState = STATE_PREPARED; | |
mVideoWidth = mp.getVideoWidth(); | |
mVideoHeight = mp.getVideoHeight(); | |
int seekToPosition = mSeekWhenPrepared; | |
if (seekToPosition != 0) | |
{ | |
seekTo(seekToPosition); | |
} else | |
{ | |
seekTo(0); | |
}; | |
if (mOnPreparedListener != null) | |
mOnPreparedListener.onPrepared(mp); | |
} | |
}; | |
TextureView.SurfaceTextureListener mSurfaceTextureListener = new SurfaceTextureListener() | |
{ | |
@Override | |
public void onSurfaceTextureSizeChanged(final SurfaceTexture surface, | |
final int width, final int height) | |
{} | |
@Override | |
public void onSurfaceTextureAvailable(final SurfaceTexture surface, | |
final int width, final int height) | |
{ | |
sf = surface; | |
if (mMediaPlayer != null) | |
{ | |
if (sf1 == null) | |
{ | |
sf1 = new Surface(surface); | |
} | |
mMediaPlayer.setSurface(sf1); | |
} | |
} | |
@Override | |
public boolean onSurfaceTextureDestroyed(final SurfaceTexture surface) | |
{ | |
return false; | |
} | |
@Override | |
public void onSurfaceTextureUpdated(final SurfaceTexture surface) | |
{} | |
}; | |
private OnCompletionListener mCompletionListener = new OnCompletionListener() | |
{ | |
public void onCompletion(MediaPlayer mp) | |
{ | |
if (mCurrentState == STATE_PLAYBACK_COMPLETED) | |
return; | |
mCurrentState = STATE_PLAYBACK_COMPLETED; | |
if (mOnCompletionListener != null) | |
mOnCompletionListener.onCompletion(mMediaPlayer); | |
} | |
}; | |
private OnErrorListener mErrorListener = new OnErrorListener() | |
{ | |
public boolean onError(MediaPlayer mp, int framework_err, int impl_err) | |
{ | |
mCurrentState = STATE_ERROR; | |
if (mOnErrorListener != null) | |
if (mOnErrorListener.onError(mMediaPlayer, framework_err, impl_err)) | |
return true; | |
return true; | |
} | |
}; | |
private OnInfoListener mInfoListener = new OnInfoListener() | |
{ | |
@Override | |
public boolean onInfo(MediaPlayer mp, int what, int extra) | |
{ | |
if (mOnInfoListener != null) | |
{ | |
mOnInfoListener.onInfo(mp, what, extra); | |
} | |
return true; | |
} | |
}; | |
public void setDisplay() | |
{ | |
if ((mMediaPlayer != null) && (sf != null) && (getSurfaceTexture() == null)) | |
setSurfaceTexture(sf); | |
} | |
@Override | |
protected void onMeasure(int widthMeasureSpec, int 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); | |
} | |
@Override | |
public void onInitializeAccessibilityEvent(AccessibilityEvent event) | |
{ | |
super.onInitializeAccessibilityEvent(event); | |
event.setClassName(VideoPlayer.class.getName()); | |
} | |
@Override | |
public void onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo info) | |
{ | |
super.onInitializeAccessibilityNodeInfo(info); | |
info.setClassName(VideoPlayer.class.getName()); | |
} | |
public int resolveAdjustedSize(int desiredSize, int measureSpec) | |
{ | |
return getDefaultSize(desiredSize, measureSpec); | |
} | |
private void initVideoView(Context ctx) | |
{ | |
setSurfaceTextureListener(mSurfaceTextureListener); | |
if ((mMediaPlayer != null) && (sf != null) | |
&& (getSurfaceTexture() == null)) | |
{ | |
setSurfaceTexture(sf); | |
} | |
setFocusable(true); | |
setFocusableInTouchMode(true); | |
requestFocus(); | |
} | |
public void setVideoPath(String path1) | |
{ | |
path = path1; | |
mSeekWhenPrepared = 0; | |
} | |
private void setListeners() | |
{ | |
mMediaPlayer.setOnPreparedListener(mPreparedListener); | |
mMediaPlayer.setOnVideoSizeChangedListener(mSizeChangedListener); | |
mMediaPlayer.setOnCompletionListener(mCompletionListener); | |
mMediaPlayer.setOnErrorListener(mErrorListener); | |
mMediaPlayer.setOnInfoListener(mInfoListener); | |
} | |
public void openVideo() | |
{ | |
if (path == null) return; | |
if (mMediaPlayer == null) | |
{ | |
try | |
{ | |
mCurrentBufferPercentage = 0; | |
mMediaPlayer = new MediaPlayer(); | |
setListeners(); | |
mMediaPlayer.setAudioStreamType(AudioManager.STREAM_MUSIC); | |
if (sf != null) | |
{ | |
if (sf1 == null) | |
sf1 = new Surface(sf); | |
mMediaPlayer.setSurface(sf1); | |
} | |
mMediaPlayer.setWakeMode(getContext(), PowerManager.PARTIAL_WAKE_LOCK); | |
mMediaPlayer.setDataSource(path); | |
mMediaPlayer.prepareAsync(); | |
mCurrentState = STATE_PREPARING; | |
} | |
catch (IOException ex) | |
{ | |
mCurrentState = STATE_ERROR; | |
mErrorListener.onError(mMediaPlayer, MediaPlayer.MEDIA_ERROR_UNKNOWN, 0); | |
// GRAVAR EM ARQUIVO DE LOG | |
Utils.AppendLog(TagNames.TagVideoPlayer + " " + | |
"[ERRO] onKeyDown(): " + ex.getMessage(), | |
_context); | |
return; | |
} | |
} | |
else | |
setListeners(); | |
} | |
public void setOnPreparedListener(OnPreparedListener l) | |
{ | |
mOnPreparedListener = l; | |
} | |
public void setOnCompletionListener(OnCompletionListener l) | |
{ | |
mOnCompletionListener = l; | |
} | |
public void setOnErrorListener(OnErrorListener l) | |
{ | |
mOnErrorListener = l; | |
} | |
public void setOnInfoListener(OnInfoListener l) | |
{ | |
mOnInfoListener = l; | |
} | |
public void release() | |
{ | |
if (mMediaPlayer != null) | |
{ | |
mMediaPlayer.release(); | |
mMediaPlayer = null; | |
mCurrentState = STATE_IDLE; | |
} | |
} | |
@Override | |
public boolean onKeyDown(int keyCode, KeyEvent event) | |
{ | |
boolean isKeyCodeSupported = keyCode != KeyEvent.KEYCODE_BACK | |
&& keyCode != KeyEvent.KEYCODE_VOLUME_UP | |
&& keyCode != KeyEvent.KEYCODE_VOLUME_DOWN | |
&& keyCode != KeyEvent.KEYCODE_MENU | |
&& keyCode != KeyEvent.KEYCODE_CALL | |
&& keyCode != KeyEvent.KEYCODE_ENDCALL; | |
if (isInPlaybackState() && isKeyCodeSupported) | |
{ | |
if (keyCode == KeyEvent.KEYCODE_HEADSETHOOK || keyCode == KeyEvent.KEYCODE_MEDIA_PLAY_PAUSE || keyCode == KeyEvent.KEYCODE_SPACE) | |
{ | |
if (mMediaPlayer.isPlaying()) | |
pause(); | |
else | |
start(); | |
return true; | |
} | |
else if (keyCode == KeyEvent.KEYCODE_MEDIA_PLAY) | |
{ | |
if (!mMediaPlayer.isPlaying()) | |
start(); | |
return true; | |
} | |
else if (keyCode == KeyEvent.KEYCODE_MEDIA_STOP || keyCode == KeyEvent.KEYCODE_MEDIA_PAUSE) | |
{ | |
if (mMediaPlayer.isPlaying()) | |
pause(); | |
return true; | |
} | |
} | |
return super.onKeyDown(keyCode, event); | |
} | |
public void setPlayPauseListener(PlayPauseListener listener) | |
{ | |
mListener = listener; | |
} | |
public int GetCurrentState() | |
{ | |
return mCurrentState; | |
} | |
interface PlayPauseListener | |
{ | |
void onPlay(); | |
void onPause(); | |
} | |
public void start() | |
{ | |
if (isInPlaybackState()) | |
{ | |
mMediaPlayer.start(); | |
mCurrentState = STATE_PLAYING; | |
} | |
if (mListener != null) | |
mListener.onPlay(); | |
} | |
public void pause() | |
{ | |
if (isInPlaybackState()) | |
{ | |
if (mMediaPlayer.isPlaying()) | |
{ | |
mMediaPlayer.pause(); | |
mCurrentState = STATE_PAUSED; | |
} | |
} | |
if (mListener != null) | |
mListener.onPause(); | |
} | |
public void stop() | |
{ | |
if (isInPlaybackState()) | |
{ | |
if (mMediaPlayer.isPlaying()) | |
{ | |
mMediaPlayer.stop(); | |
mCurrentState = STATE_STOPED; | |
} | |
} | |
//if (mListener != null) | |
//mListener.onStop(); | |
} | |
public void reset() | |
{ | |
mMediaPlayer.reset(); | |
} | |
public int getDuration() | |
{ | |
if (isInPlaybackState()) | |
return mMediaPlayer.getDuration(); | |
return -1; | |
} | |
public int getCurrentPosition() | |
{ | |
if (isInPlaybackState()) | |
return mMediaPlayer.getCurrentPosition(); | |
return 0; | |
} | |
interface SeekListener | |
{ | |
void onSeek(int msec); | |
void onSeekComplete(MediaPlayer mp); | |
} | |
public void seekTo(int msec) | |
{ | |
mMediaPlayer.seekTo(msec); | |
} | |
public boolean isPlaying() | |
{ | |
return isInPlaybackState() && mMediaPlayer.isPlaying(); | |
} | |
protected boolean isInPlaybackState() | |
{ | |
return (mMediaPlayer != null && mCurrentState != STATE_ERROR | |
&& mCurrentState != STATE_IDLE && mCurrentState != STATE_PREPARING); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment