rpicms-android

Android app for the RPICMS.
git clone git://archive.git.mtrnord.blog/RpicmsTeam/rpicms-android.git
Log | Files | Refs

PlayerActivity.java (14035B)


      1 package de.nordgedanken.rpicms;
      2 
      3 import android.app.Activity;
      4 import android.content.Intent;
      5 import android.media.MediaPlayer;
      6 import android.media.MediaPlayer.OnCompletionListener;
      7 import android.media.MediaPlayer.OnErrorListener;
      8 import android.media.MediaPlayer.OnPreparedListener;
      9 import android.os.Bundle;
     10 import android.os.Handler;
     11 import android.util.DisplayMetrics;
     12 import android.util.Log;
     13 import android.view.KeyEvent;
     14 import android.view.MenuItem;
     15 import android.view.View;
     16 import android.widget.ImageView;
     17 import android.widget.ProgressBar;
     18 import android.widget.RelativeLayout.LayoutParams;
     19 import android.widget.SeekBar;
     20 import android.widget.TextView;
     21 import android.widget.VideoView;
     22 
     23 import java.util.Timer;
     24 import java.util.TimerTask;
     25 
     26 public class PlayerActivity extends Activity {
     27 
     28     private static final String TAG = "PlayerActivity";
     29 
     30     private static final int HIDE_CONTROLLER_TIME = 5000;
     31     private static final int SEEKBAR_DELAY_TIME = 100;
     32     private static final int SEEKBAR_INTERVAL_TIME = 1000;
     33     private static final int MIN_SCRUB_TIME = 3000;
     34     private static final int SCRUB_SEGMENT_DIVISOR = 30;
     35     private static final double MEDIA_BAR_TOP_MARGIN = 0.8;
     36     private static final double MEDIA_BAR_RIGHT_MARGIN = 0.2;
     37     private static final double MEDIA_BAR_BOTTOM_MARGIN = 0.0;
     38     private static final double MEDIA_BAR_LEFT_MARGIN = 0.2;
     39     private static final double MEDIA_BAR_HEIGHT = 0.1;
     40     private static final double MEDIA_BAR_WIDTH = 0.9;
     41 
     42     private VideoView mVideoView;
     43     private TextView mStartText;
     44     private TextView mEndText;
     45     private SeekBar mSeekbar;
     46     private ImageView mPlayPause;
     47     private ProgressBar mLoading;
     48     private View mControllers;
     49     private View mContainer;
     50     private Timer mSeekbarTimer;
     51     private Timer mControllersTimer;
     52     private PlaybackState mPlaybackState;
     53     private final Handler mHandler = new Handler();
     54     private Movie mSelectedMovie;
     55     private boolean mShouldStartPlayback;
     56     private boolean mControlersVisible;
     57     private int mDuration;
     58     private DisplayMetrics mMetrics;
     59 
     60     /*
     61      * List of various states that we can be in
     62      */
     63     public static enum PlaybackState {
     64         PLAYING, PAUSED, BUFFERING, IDLE;
     65     }
     66 
     67     @Override
     68     public void onCreate(Bundle savedInstanceState) {
     69         super.onCreate(savedInstanceState);
     70         setContentView(R.layout.activity_player);
     71 
     72         mMetrics = new DisplayMetrics();
     73         getWindowManager().getDefaultDisplay().getMetrics(mMetrics);
     74 
     75         loadViews();
     76         setupController();
     77         setupControlsCallbacks();
     78         startVideoPlayer();
     79         updateMetadata(true);
     80     }
     81 
     82     private void startVideoPlayer() {
     83         Bundle b = getIntent().getExtras();
     84         mSelectedMovie = (Movie) getIntent().getSerializableExtra(getResources().getString(R.string.movie));
     85         if (null != b) {
     86             mShouldStartPlayback = b.getBoolean(getResources().getString(R.string.should_start));
     87             int startPosition = b.getInt(getResources().getString(R.string.start_position), 0);
     88             mVideoView.setVideoPath(mSelectedMovie.getVideoUrl());
     89             if (mShouldStartPlayback) {
     90                 mPlaybackState = PlaybackState.PLAYING;
     91                 updatePlayButton(mPlaybackState);
     92                 if (startPosition > 0) {
     93                     mVideoView.seekTo(startPosition);
     94                 }
     95                 mVideoView.start();
     96                 mPlayPause.requestFocus();
     97                 startControllersTimer();
     98             } else {
     99                 updatePlaybackLocation();
    100                 mPlaybackState = PlaybackState.PAUSED;
    101                 updatePlayButton(mPlaybackState);
    102             }
    103         }
    104     }
    105 
    106     private void updatePlaybackLocation() {
    107         if (mPlaybackState == PlaybackState.PLAYING ||
    108                 mPlaybackState == PlaybackState.BUFFERING) {
    109             startControllersTimer();
    110         } else {
    111             stopControllersTimer();
    112         }
    113     }
    114 
    115     private void play(int position) {
    116         startControllersTimer();
    117         mVideoView.seekTo(position);
    118         mVideoView.start();
    119         restartSeekBarTimer();
    120     }
    121 
    122     private void stopSeekBarTimer() {
    123         Log.d(TAG, "Stopped TrickPlay Timer");
    124         if (null != mSeekbarTimer) {
    125             mSeekbarTimer.cancel();
    126         }
    127     }
    128 
    129     private void restartSeekBarTimer() {
    130         stopSeekBarTimer();
    131         mSeekbarTimer = new Timer();
    132         mSeekbarTimer.scheduleAtFixedRate(new UpdateSeekbarTask(), SEEKBAR_DELAY_TIME,
    133                 SEEKBAR_INTERVAL_TIME);
    134     }
    135 
    136     private void stopControllersTimer() {
    137         if (null != mControllersTimer) {
    138             mControllersTimer.cancel();
    139         }
    140     }
    141 
    142     private void startControllersTimer() {
    143         if (null != mControllersTimer) {
    144             mControllersTimer.cancel();
    145         }
    146         mControllersTimer = new Timer();
    147         mControllersTimer.schedule(new HideControllersTask(), HIDE_CONTROLLER_TIME);
    148     }
    149 
    150     private void updateControlersVisibility(boolean show) {
    151         if (show) {
    152             mControllers.setVisibility(View.VISIBLE);
    153         } else {
    154             mControllers.setVisibility(View.INVISIBLE);
    155         }
    156     }
    157 
    158     @Override
    159     protected void onPause() {
    160         super.onPause();
    161         Log.d(TAG, "onPause() was called");
    162         if (null != mSeekbarTimer) {
    163             mSeekbarTimer.cancel();
    164             mSeekbarTimer = null;
    165         }
    166         if (null != mControllersTimer) {
    167             mControllersTimer.cancel();
    168         }
    169         mVideoView.pause();
    170         mPlaybackState = PlaybackState.PAUSED;
    171         updatePlayButton(PlaybackState.PAUSED);
    172     }
    173 
    174     @Override
    175     protected void onStop() {
    176         Log.d(TAG, "onStop() was called");
    177         super.onStop();
    178     }
    179 
    180     @Override
    181     protected void onDestroy() {
    182         Log.d(TAG, "onDestroy() is called");
    183         stopControllersTimer();
    184         stopSeekBarTimer();
    185         super.onDestroy();
    186     }
    187 
    188     @Override
    189     protected void onStart() {
    190         Log.d(TAG, "onStart was called");
    191         super.onStart();
    192     }
    193 
    194     @Override
    195     protected void onResume() {
    196         Log.d(TAG, "onResume() was called");
    197         super.onResume();
    198     }
    199 
    200     private class HideControllersTask extends TimerTask {
    201         @Override
    202         public void run() {
    203             mHandler.post(new Runnable() {
    204                 @Override
    205                 public void run() {
    206                     updateControlersVisibility(false);
    207                     mControlersVisible = false;
    208                 }
    209             });
    210 
    211         }
    212     }
    213 
    214     private class UpdateSeekbarTask extends TimerTask {
    215 
    216         @Override
    217         public void run() {
    218             mHandler.post(new Runnable() {
    219 
    220                 @Override
    221                 public void run() {
    222                     int currentPos = 0;
    223                     currentPos = mVideoView.getCurrentPosition();
    224                     updateSeekbar(currentPos, mDuration);
    225                 }
    226             });
    227         }
    228     }
    229 
    230     private class BackToDetailTask extends TimerTask {
    231 
    232         @Override
    233         public void run() {
    234             mHandler.post(new Runnable() {
    235                 @Override
    236                 public void run() {
    237                     Intent intent = new Intent(PlayerActivity.this, DetailsActivity.class);
    238                     intent.putExtra(getResources().getString(R.string.movie), mSelectedMovie);
    239                     startActivity(intent);
    240                 }
    241             });
    242 
    243         }
    244     }
    245 
    246     private void setupController() {
    247 
    248         int w = (int) (mMetrics.widthPixels * MEDIA_BAR_WIDTH);
    249         int h = (int) (mMetrics.heightPixels * MEDIA_BAR_HEIGHT);
    250         int marginLeft = (int) (mMetrics.widthPixels * MEDIA_BAR_LEFT_MARGIN);
    251         int marginTop = (int) (mMetrics.heightPixels * MEDIA_BAR_TOP_MARGIN);
    252         int marginRight = (int) (mMetrics.widthPixels * MEDIA_BAR_RIGHT_MARGIN);
    253         int marginBottom = (int) (mMetrics.heightPixels * MEDIA_BAR_BOTTOM_MARGIN);
    254         LayoutParams lp = new LayoutParams(w, h);
    255         lp.setMargins(marginLeft, marginTop, marginRight, marginBottom);
    256         mControllers.setLayoutParams(lp);
    257         mStartText.setText(getResources().getString(R.string.init_text));
    258         mEndText.setText(getResources().getString(R.string.init_text));
    259     }
    260 
    261     private void setupControlsCallbacks() {
    262 
    263         mVideoView.setOnErrorListener(new OnErrorListener() {
    264 
    265             @Override
    266             public boolean onError(MediaPlayer mp, int what, int extra) {
    267                 String msg = "";
    268                 if (extra == MediaPlayer.MEDIA_ERROR_TIMED_OUT) {
    269                     msg = getString(R.string.video_error_media_load_timeout);
    270                 } else if (what == MediaPlayer.MEDIA_ERROR_SERVER_DIED) {
    271                     msg = getString(R.string.video_error_server_unaccessible);
    272                 } else {
    273                     msg = getString(R.string.video_error_unknown_error);
    274                 }
    275                 mVideoView.stopPlayback();
    276                 mPlaybackState = PlaybackState.IDLE;
    277                 return false;
    278             }
    279         });
    280 
    281         mVideoView.setOnPreparedListener(new OnPreparedListener() {
    282 
    283             @Override
    284             public void onPrepared(MediaPlayer mp) {
    285                 Log.d(TAG, "onPrepared is reached");
    286                 mDuration = mp.getDuration();
    287                 mEndText.setText(Utils.formatMillis(mDuration));
    288                 mSeekbar.setMax(mDuration);
    289                 restartSeekBarTimer();
    290             }
    291         });
    292 
    293         mVideoView.setOnCompletionListener(new OnCompletionListener() {
    294 
    295             @Override
    296             public void onCompletion(MediaPlayer mp) {
    297                 stopSeekBarTimer();
    298                 mPlaybackState = PlaybackState.IDLE;
    299                 updatePlayButton(PlaybackState.IDLE);
    300                 mControllersTimer = new Timer();
    301                 mControllersTimer.schedule(new BackToDetailTask(), HIDE_CONTROLLER_TIME);
    302             }
    303         });
    304     }
    305 
    306     /*
    307      * @Override public boolean onKeyDown(int keyCode, KeyEvent event) { return
    308      * super.onKeyDown(keyCode, event); }
    309      */
    310 
    311     @Override
    312     public boolean onKeyDown(int keyCode, KeyEvent event) {
    313         int currentPos = 0;
    314         int delta = (int) (mDuration / SCRUB_SEGMENT_DIVISOR);
    315         if (delta < MIN_SCRUB_TIME)
    316             delta = MIN_SCRUB_TIME;
    317 
    318         Log.v("keycode", "duration " + mDuration + " delta:" + delta);
    319         if (!mControlersVisible) {
    320             updateControlersVisibility(true);
    321         }
    322         switch (keyCode) {
    323             case KeyEvent.KEYCODE_DPAD_CENTER:
    324                 return true;
    325             case KeyEvent.KEYCODE_DPAD_DOWN:
    326                 return true;
    327             case KeyEvent.KEYCODE_DPAD_LEFT:
    328                 currentPos = mVideoView.getCurrentPosition();
    329                 currentPos -= delta;
    330                 if (currentPos > 0)
    331                     play(currentPos);
    332                 return true;
    333             case KeyEvent.KEYCODE_DPAD_RIGHT:
    334                 currentPos = mVideoView.getCurrentPosition();
    335                 currentPos += delta;
    336                 if (currentPos < mDuration)
    337                     play(currentPos);
    338                 return true;
    339             case KeyEvent.KEYCODE_DPAD_UP:
    340                 return true;
    341         }
    342 
    343         return super.onKeyDown(keyCode, event);
    344     }
    345 
    346     private void updateSeekbar(int position, int duration) {
    347         mSeekbar.setProgress(position);
    348         mSeekbar.setMax(duration);
    349         mStartText.setText(Utils.formatMillis(position));
    350         mEndText.setText(Utils.formatMillis(duration));
    351     }
    352 
    353     private void updatePlayButton(PlaybackState state) {
    354         switch (state) {
    355             case PLAYING:
    356                 mLoading.setVisibility(View.INVISIBLE);
    357                 mPlayPause.setVisibility(View.VISIBLE);
    358                 mPlayPause.setImageDrawable(
    359                         getResources().getDrawable(R.drawable.ic_pause_playcontrol_normal));
    360                 break;
    361             case PAUSED:
    362             case IDLE:
    363                 mLoading.setVisibility(View.INVISIBLE);
    364                 mPlayPause.setVisibility(View.VISIBLE);
    365                 mPlayPause.setImageDrawable(
    366                         getResources().getDrawable(R.drawable.ic_play_playcontrol_normal));
    367                 break;
    368             case BUFFERING:
    369                 mPlayPause.setVisibility(View.INVISIBLE);
    370                 mLoading.setVisibility(View.VISIBLE);
    371                 break;
    372             default:
    373                 break;
    374         }
    375     }
    376 
    377     private void updateMetadata(boolean visible) {
    378         mVideoView.invalidate();
    379     }
    380 
    381     @Override
    382     public boolean onOptionsItemSelected(MenuItem item) {
    383         return true;
    384     }
    385 
    386     private void loadViews() {
    387         mVideoView = (VideoView) findViewById(R.id.videoView);
    388         mStartText = (TextView) findViewById(R.id.startText);
    389         mEndText = (TextView) findViewById(R.id.endText);
    390         mSeekbar = (SeekBar) findViewById(R.id.seekBar);
    391         mPlayPause = (ImageView) findViewById(R.id.playpause);
    392         mLoading = (ProgressBar) findViewById(R.id.progressBar);
    393         mControllers = findViewById(R.id.controllers);
    394         mContainer = findViewById(R.id.container);
    395 
    396         mVideoView.setOnClickListener(mPlayPauseHandler);
    397     }
    398 
    399     View.OnClickListener mPlayPauseHandler = new View.OnClickListener() {
    400         public void onClick(View v) {
    401             Log.d(TAG, "clicked play pause button");
    402 
    403             if (!mControlersVisible) {
    404                 updateControlersVisibility(true);
    405             }
    406 
    407             if (mPlaybackState == PlaybackState.PAUSED) {
    408                 mPlaybackState = PlaybackState.PLAYING;
    409                 updatePlayButton(mPlaybackState);
    410                 mVideoView.start();
    411                 startControllersTimer();
    412             } else {
    413                 mVideoView.pause();
    414                 mPlaybackState = PlaybackState.PAUSED;
    415                 updatePlayButton(PlaybackState.PAUSED);
    416                 stopControllersTimer();
    417             }
    418         }
    419     };
    420 }