Advertisement
Guest User

Untitled

a guest
Dec 9th, 2013
6,296
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Java 17.53 KB | None | 0 0
  1. package com.wisemandesigns.demo.widget;
  2.  
  3. //
  4. //VideoView
  5. //
  6. //
  7. //Created by Alex Ross on 1/29/13
  8. //Modified to accept a Matrix by Wiseman Designs
  9. //
  10.  
  11. import java.io.IOException;
  12.  
  13. import android.app.Activity;
  14. import android.content.Context;
  15. import android.content.Intent;
  16. import android.graphics.Matrix;
  17. import android.graphics.SurfaceTexture;
  18. import android.media.AudioManager;
  19. import android.media.MediaPlayer;
  20. import android.net.Uri;
  21. import android.util.AttributeSet;
  22. import android.util.Log;
  23. import android.view.KeyEvent;
  24. import android.view.MotionEvent;
  25. import android.view.Surface;
  26. import android.view.TextureView;
  27. import android.view.View;
  28. import android.widget.MediaController;
  29. import android.widget.MediaController.MediaPlayerControl;
  30.  
  31. public class VideoView extends TextureView implements MediaPlayerControl{
  32.  
  33.  private static final String LOG_TAG = "VideoView";
  34.  
  35.  // all possible internal states
  36.  private static final int STATE_ERROR              = -1;
  37.  private static final int STATE_IDLE               = 0;
  38.  private static final int STATE_PREPARING          = 1;
  39.  private static final int STATE_PREPARED           = 2;
  40.  private static final int STATE_PLAYING            = 3;
  41.  private static final int STATE_PAUSED             = 4;
  42.  private static final int STATE_PLAYBACK_COMPLETED = 5;
  43.  
  44.  public int number;
  45.  
  46.  // currentState is a VideoView object's current state.
  47.  // targetState is the state that a method caller intends to reach.
  48.  // For instance, regardless the VideoView object's current state,
  49.  // calling pause() intends to bring the object to a target state
  50.  // of STATE_PAUSED.
  51.  private int currentState = STATE_IDLE;
  52.  private int targetState = STATE_IDLE;
  53.  
  54.  // Stuff we need for playing and showing a video
  55.  private MediaPlayer mediaPlayer;
  56.  private int videoWidth;
  57.  private int videoHeight;
  58.  private int surfaceWidth;
  59.  private int surfaceHeight;
  60.  private int audioSession;
  61.  private SurfaceTexture surfaceTexture;
  62.  private Surface surface;
  63.  private MediaController mediaController;
  64.  private MediaPlayer.OnCompletionListener onCompletionListener;
  65.  private MediaPlayer.OnPreparedListener onPreparedListener;
  66.  private int currentBufferPercentage;
  67.  private MediaPlayer.OnErrorListener onErrorListener;
  68.  private MediaPlayer.OnInfoListener onInfoListener;
  69.  
  70.  private int mSeekWhenPrepared;  // recording the seek position while preparing
  71.  private boolean mCanPause;
  72.  private boolean mCanSeekBack;
  73.  private boolean mCanSeekForward;
  74.  private Uri uri;
  75.  
  76.  //scale stuff
  77.  private float widthScale = 1.0f;
  78.  private float heightScale = 1.0f;
  79.  
  80.  private Context mContext;
  81.  
  82.  public VideoView(final Context context) {
  83.      super(context);
  84.      mContext = context;
  85.      initVideoView();
  86.  }
  87.  
  88.  public VideoView(final Context context, final AttributeSet attrs) {
  89.      super(context, attrs);
  90.      mContext = context;
  91.      initVideoView();
  92.  }
  93.  
  94.  public VideoView(Context context, AttributeSet attrs, int defStyle) {
  95.      super(context, attrs, defStyle);
  96.      mContext = context;
  97.      initVideoView();
  98.  }
  99.  
  100.  public void initVideoView() {
  101.      Log.d(LOG_TAG, "Initializing video view.");
  102.      videoHeight = 0;
  103.      videoWidth = 0;
  104.      setFocusable(false);
  105.      setSurfaceTextureListener(surfaceTextureListener);
  106.  }
  107.  
  108.  public int resolveAdjustedSize(int desiredSize, int measureSpec) {
  109.      Log.d(LOG_TAG, "Resolve called.");
  110.      int result = desiredSize;
  111.      int specMode = MeasureSpec.getMode(measureSpec);
  112.      int specSize =  MeasureSpec.getSize(measureSpec);
  113.  
  114.      switch (specMode) {
  115.          case MeasureSpec.UNSPECIFIED:
  116.              /* Parent says we can be as big as we want. Just don't be larger
  117.               * than max size imposed on ourselves.
  118.               */
  119.              result = desiredSize;
  120.              break;
  121.  
  122.          case MeasureSpec.AT_MOST:
  123.              /* Parent says we can be as big as we want, up to specSize.
  124.               * Don't be larger than specSize, and don't be larger than
  125.               * the max size imposed on ourselves.
  126.               */
  127.              result = Math.min(desiredSize, specSize);
  128.              break;
  129.  
  130.          case MeasureSpec.EXACTLY:
  131.              // No choice. Do what we are told.
  132.              result = specSize;
  133.              break;
  134.      }
  135.      return result;
  136.  }
  137.  
  138.  public void setVideoPath(String path) {
  139.      Log.d(LOG_TAG, "Setting video path to: " + path);
  140.      setVideoURI(Uri.parse(path));
  141.  }
  142.  
  143.  public void setVideoURI(Uri _videoURI) {
  144.      uri = _videoURI;
  145.      requestLayout();
  146.      invalidate();
  147.      openVideo();
  148.  }
  149.  
  150.  public void setSurfaceTexture(SurfaceTexture _surfaceTexture) {
  151.      surfaceTexture = _surfaceTexture;
  152.  }
  153.  
  154.  public void openVideo() {
  155.      if ((uri == null) || (surfaceTexture == null)) {
  156.          Log.d(LOG_TAG, "Cannot open video, uri or surface is null number " + number);
  157.          return;
  158.      }
  159.      // Tell the music playback service to pause
  160.      // TODO: these constants need to be published somewhere in the framework.
  161.      Intent i = new Intent("com.android.music.musicservicecommand");
  162.      i.putExtra("command", "pause");
  163.      mContext.sendBroadcast(i);
  164.      Log.d(LOG_TAG, "Opening video.");
  165.      release(false);
  166.      try {
  167.          surface = new Surface(surfaceTexture);
  168.          Log.d(LOG_TAG, "Creating media player number " + number);
  169.          mediaPlayer = new MediaPlayer();
  170.          
  171.          if (audioSession != 0) {
  172.              mediaPlayer.setAudioSessionId(audioSession);
  173.          } else {
  174.              audioSession = mediaPlayer.getAudioSessionId();
  175.          }
  176.          
  177.          Log.d(LOG_TAG, "Setting surface.");
  178.          mediaPlayer.setSurface(surface);
  179.          Log.d(LOG_TAG, "Setting data source.");
  180.          mediaPlayer.setDataSource(mContext, uri);
  181.          Log.d(LOG_TAG, "Setting media player listeners.");
  182.          mediaPlayer.setOnBufferingUpdateListener(bufferingUpdateListener);
  183.          mediaPlayer.setOnCompletionListener(completeListener);
  184.          mediaPlayer.setOnPreparedListener(preparedListener);
  185.          mediaPlayer.setOnErrorListener(errorListener);
  186.          mediaPlayer.setOnVideoSizeChangedListener(videoSizeChangedListener);
  187.          mediaPlayer.setAudioStreamType(AudioManager.STREAM_MUSIC);
  188.          Log.d(LOG_TAG, "Preparing media player.");
  189.          mediaPlayer.prepareAsync();
  190.          currentState = STATE_PREPARING;
  191.          attachMediaController();
  192.      } catch (IllegalStateException e) {
  193.          currentState = STATE_ERROR;
  194.          targetState = STATE_ERROR;
  195.          Log.d(LOG_TAG, e.getMessage()); //TODO auto-generated catch block
  196.      } catch (IOException e) {
  197.          currentState = STATE_ERROR;
  198.          targetState = STATE_ERROR;
  199.          Log.d(LOG_TAG, e.getMessage()); //TODO auto-generated catch block
  200.      }
  201.  }
  202.  
  203.  public void stopPlayback() {
  204.      if (mediaPlayer != null) {
  205.          mediaPlayer.stop();
  206.          mediaPlayer.release();
  207.          mediaPlayer = null;
  208.      }
  209.  }
  210.  
  211.  @Override
  212.  protected void onMeasure(final int widthMeasureSpec, final int heightMeasureSpec) {
  213.      // Will resize the view if the video dimensions have been found.
  214.      // video dimensions are found after onPrepared has been called by MediaPlayer
  215.      Log.d(LOG_TAG, "onMeasure number " + number);
  216.      int width = getDefaultSize(videoWidth, widthMeasureSpec);
  217.      int height = getDefaultSize(videoHeight, heightMeasureSpec);
  218.      if ((videoWidth > 0) && (videoHeight > 0)) {
  219.          if ((videoWidth * height) > (width * videoHeight)) {
  220.              Log.d(LOG_TAG, "Image too tall, correcting.");
  221.              height = (width * videoHeight) / videoWidth;
  222.          } else if ((videoWidth * height) < (width * videoHeight)) {
  223.              Log.d(LOG_TAG, "Image too wide, correcting.");
  224.              width = (height * videoWidth) / videoHeight;
  225.          } else {
  226.              Log.d(LOG_TAG, "Aspect ratio is correct.");
  227.          }
  228.      }
  229.      Log.d(LOG_TAG, "Setting size: " + width + '/' + height + " for number " + number);
  230.      setMeasuredDimension((int)(width * widthScale), (int)(height * heightScale));
  231.  }
  232.  
  233.  // Listeners
  234.  private MediaPlayer.OnBufferingUpdateListener bufferingUpdateListener = new MediaPlayer.OnBufferingUpdateListener() {
  235.      @Override
  236.      public void onBufferingUpdate(final MediaPlayer mp, final int percent) {
  237.          currentBufferPercentage = percent;
  238.      }
  239.  };
  240.  
  241.  private MediaPlayer.OnCompletionListener completeListener = new MediaPlayer.OnCompletionListener() {
  242.      @Override
  243.      public void onCompletion(final MediaPlayer mp) {
  244.          currentState = STATE_PLAYBACK_COMPLETED;
  245.          targetState = STATE_PLAYBACK_COMPLETED;
  246.          Log.d(LOG_TAG, "Video completed number " + number);
  247.          surface.release();
  248.          
  249.          ((Activity) getContext()).finish();
  250.      }
  251.  };
  252.  
  253.  private MediaPlayer.OnPreparedListener preparedListener = new MediaPlayer.OnPreparedListener() {
  254.      @Override
  255.      public void onPrepared(final MediaPlayer mp) {
  256.          currentState = STATE_PREPARED;
  257.          Log.d(LOG_TAG, "Video prepared for " + number);
  258.          videoWidth = mp.getVideoWidth();
  259.          videoHeight = mp.getVideoHeight();
  260.          
  261.          mCanPause = mCanSeekBack = mCanSeekForward = true;
  262.          
  263.          if (mediaController != null) {
  264.              mediaController.setEnabled(true);
  265.          }
  266.          
  267.          requestLayout();
  268.          invalidate();
  269.          if ((videoWidth != 0) && (videoHeight != 0)) {
  270.              Log.d(LOG_TAG, "Video size for number " + number + ": " + videoWidth + '/' + videoHeight);
  271.              if (targetState == STATE_PLAYING) {
  272.                  mediaPlayer.start();
  273.              }
  274.          } else {
  275.              if (targetState == STATE_PLAYING) {
  276.                  mediaPlayer.start();
  277.              }
  278.          }
  279.      }
  280.  };
  281.  
  282.  private MediaPlayer.OnVideoSizeChangedListener videoSizeChangedListener = new MediaPlayer.OnVideoSizeChangedListener() {
  283.      @Override
  284.      public void onVideoSizeChanged(final MediaPlayer mp, final int width, final int height) {
  285.          Log.d(LOG_TAG, "Video size changed " + width + '/' + height + " number " + number);
  286.      }
  287.  };
  288.  
  289.  private MediaPlayer.OnErrorListener errorListener = new MediaPlayer.OnErrorListener() {
  290.      @Override
  291.      public boolean onError(final MediaPlayer mp, final int what, final int extra) {
  292.          currentState = STATE_ERROR;
  293.          targetState = STATE_ERROR;
  294.          Log.e(LOG_TAG, "There was an error during video playback.");
  295.          return true;
  296.      }
  297.  };
  298.  
  299.  public void setMediaController(MediaController controller) {
  300.      if (mediaController != null) {
  301.          mediaController.hide();
  302.      }
  303.      mediaController = controller;
  304.      attachMediaController();
  305.  }
  306.  
  307.  private void attachMediaController() {
  308.      if (mediaPlayer != null && mediaController != null) {
  309.          mediaController.setMediaPlayer(this);
  310.          View anchorView = this.getParent() instanceof View ?
  311.                  (View)this.getParent() : this;
  312.                  mediaController.setAnchorView(anchorView);
  313.                  mediaController.setEnabled(isInPlaybackState());
  314.      }
  315.  }
  316.  
  317.      /*
  318.       * release the media player in any state
  319.       */
  320.      private void release(boolean cleartargetstate) {
  321.          Log.d(LOG_TAG, "Releasing media player.");
  322.          if (mediaPlayer != null) {
  323.              mediaPlayer.reset();
  324.              mediaPlayer.release();
  325.              mediaPlayer = null;
  326.              currentState = STATE_IDLE;
  327.              if (cleartargetstate) {
  328.                  targetState  = STATE_IDLE;
  329.              }
  330.              Log.d(LOG_TAG, "Released media player.");
  331.          } else {
  332.              Log.d(LOG_TAG, "Media player was null, did not release.");
  333.          }
  334.      }
  335.    
  336.      @Override
  337.      public boolean onTouchEvent(MotionEvent ev) {
  338.          if (isInPlaybackState() && mediaController != null) {
  339.              toggleMediaControlsVisiblity();
  340.          }
  341.          return false;
  342.      }
  343.    
  344.      @Override
  345.      public boolean onTrackballEvent(MotionEvent ev) {
  346.          if (isInPlaybackState() && mediaController != null) {
  347.              toggleMediaControlsVisiblity();
  348.          }
  349.          return false;
  350.      }
  351.    
  352.      @Override
  353.      public boolean onKeyDown(int keyCode, KeyEvent event)
  354.      {
  355.          boolean isKeyCodeSupported = keyCode != KeyEvent.KEYCODE_BACK &&
  356.                                       keyCode != KeyEvent.KEYCODE_VOLUME_UP &&
  357.                                       keyCode != KeyEvent.KEYCODE_VOLUME_DOWN &&
  358.                                       keyCode != KeyEvent.KEYCODE_VOLUME_MUTE &&
  359.                                       keyCode != KeyEvent.KEYCODE_MENU &&
  360.                                       keyCode != KeyEvent.KEYCODE_CALL &&
  361.                                       keyCode != KeyEvent.KEYCODE_ENDCALL;
  362.          if (isInPlaybackState() && isKeyCodeSupported && mediaController != null) {
  363.              if (keyCode == KeyEvent.KEYCODE_HEADSETHOOK ||
  364.                      keyCode == KeyEvent.KEYCODE_MEDIA_PLAY_PAUSE) {
  365.                  if (mediaPlayer.isPlaying()) {
  366.                      pause();
  367.                      mediaController.show();
  368.                  } else {
  369.                      start();
  370.                      mediaController.hide();
  371.                  }
  372.                  return true;
  373.              } else if (keyCode == KeyEvent.KEYCODE_MEDIA_PLAY) {
  374.                  if (!mediaPlayer.isPlaying()) {
  375.                      start();
  376.                      mediaController.hide();
  377.                  }
  378.                  return true;
  379.              } else if (keyCode == KeyEvent.KEYCODE_MEDIA_STOP
  380.                      || keyCode == KeyEvent.KEYCODE_MEDIA_PAUSE) {
  381.                  if (mediaPlayer.isPlaying()) {
  382.                      pause();
  383.                      mediaController.show();
  384.                  }
  385.                  return true;
  386.              } else {
  387.                  toggleMediaControlsVisiblity();
  388.              }
  389.          }
  390.    
  391.          return super.onKeyDown(keyCode, event);
  392.      }
  393.    
  394.      private void toggleMediaControlsVisiblity() {
  395.          if (mediaController.isShowing()) {
  396.              mediaController.hide();
  397.          } else {
  398.              mediaController.show();
  399.          }
  400.      }
  401.    
  402.      @Override
  403.      public void start() {
  404.          if (isInPlaybackState()) {
  405.              mediaPlayer.start();
  406.              currentState = STATE_PLAYING;
  407.          }
  408.          targetState = STATE_PLAYING;
  409.      }
  410.    
  411.      @Override
  412.      public void pause() {
  413.          if (isInPlaybackState()) {
  414.              if (mediaPlayer.isPlaying()) {
  415.                  mediaPlayer.pause();
  416.                  currentState = STATE_PAUSED;
  417.              }
  418.          }
  419.          targetState = STATE_PAUSED;
  420.      }
  421.    
  422.      public void suspend() {
  423.          release(false);
  424.      }
  425.    
  426.      public void resume() {
  427.          openVideo();
  428.      }
  429.    
  430.      @Override
  431.      public int getDuration() {
  432.          if (isInPlaybackState()) {
  433.              return mediaPlayer.getDuration();
  434.          }
  435.    
  436.          return -1;
  437.      }
  438.    
  439.      @Override
  440.      public int getCurrentPosition() {
  441.          if (isInPlaybackState()) {
  442.              return mediaPlayer.getCurrentPosition();
  443.          }
  444.          return 0;
  445.      }
  446.    
  447.      @Override
  448.      public void seekTo(int msec) {
  449.          if (isInPlaybackState()) {
  450.              mediaPlayer.seekTo(msec);
  451.              mSeekWhenPrepared = 0;
  452.          } else {
  453.              mSeekWhenPrepared = msec;
  454.          }
  455.      }
  456.    
  457.      @Override
  458.      public boolean isPlaying() {
  459.          return isInPlaybackState() && mediaPlayer.isPlaying();
  460.      }
  461.    
  462.      @Override
  463.      public int getBufferPercentage() {
  464.          if (mediaPlayer != null) {
  465.              return currentBufferPercentage;
  466.          }
  467.          return 0;
  468.      }
  469.    
  470.      private boolean isInPlaybackState() {
  471.          return (mediaPlayer != null &&
  472.                  currentState != STATE_ERROR &&
  473.                  currentState != STATE_IDLE &&
  474.                  currentState != STATE_PREPARING);
  475.      }
  476.    
  477.      @Override
  478.      public boolean canPause() {
  479.          return mCanPause;
  480.      }
  481.    
  482.      @Override
  483.      public boolean canSeekBackward() {
  484.          return mCanSeekBack;
  485.      }
  486.    
  487.      @Override
  488.      public boolean canSeekForward() {
  489.          return mCanSeekForward;
  490.      }
  491.    
  492.      public int getAudioSessionId() {
  493.          if (audioSession == 0) {
  494.              MediaPlayer foo = new MediaPlayer();
  495.             audioSession = foo.getAudioSessionId();
  496.              foo.release();
  497.          }
  498.          return audioSession;
  499.      }
  500.      
  501.      public void setMatrix(Matrix mMatrix)
  502.      {
  503.          this.setTransform(mMatrix);
  504.      }
  505.      
  506.      public void setViewScale(float width, float height)
  507.      {
  508.          this.widthScale = width;
  509.          this.heightScale = height;
  510.          this.invalidate();
  511.      }
  512.  
  513.  SurfaceTextureListener surfaceTextureListener = new SurfaceTextureListener() {
  514.      @Override
  515.      public void onSurfaceTextureAvailable(final SurfaceTexture surface, final int width, final int height) {
  516.          Log.d(LOG_TAG, "Surface texture now avaialble.");
  517.          surfaceTexture = surface;
  518.          openVideo();
  519.      }
  520.  
  521.      @Override
  522.      public void onSurfaceTextureSizeChanged(final SurfaceTexture surface, final int width, final int height) {
  523.          Log.d(LOG_TAG, "Resized surface texture: " + width + '/' + height);
  524.          surfaceWidth = width;
  525.          surfaceHeight = height;
  526.          boolean isValidState =  (targetState == STATE_PLAYING);
  527.          boolean hasValidSize = (videoWidth == width && videoHeight == height);
  528.          if (mediaPlayer != null && isValidState && hasValidSize) {
  529.              start();
  530.          }
  531.      }
  532.  
  533.      @Override
  534.      public boolean onSurfaceTextureDestroyed(final SurfaceTexture surface) {
  535.          Log.i(LOG_TAG, "Destroyed surface number " + number);
  536.          
  537.          if (mediaController != null) mediaController.hide();
  538.          
  539.          if (mediaPlayer != null) {
  540.              mediaPlayer.reset();
  541.              mediaPlayer.release();
  542.              mediaPlayer = null;
  543.          }
  544.          
  545.          return false;
  546.      }
  547.  
  548.      @Override
  549.      public void onSurfaceTextureUpdated(final SurfaceTexture surface) {
  550.  
  551.      }
  552.  };
  553. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement