Update media controller sample.
Now use the new abstractions of TransportMediator. Guess I should
also change the name of this sample to match it... that'll be for
a future change. :)
Change-Id: I932f8215bba51dfaa1bd5766ab9551c9dc440657
diff --git a/samples/Support4Demos/src/com/example/android/supportv4/media/MediaController.java b/samples/Support4Demos/src/com/example/android/supportv4/media/MediaController.java
index e7f9e08..d7d513d 100644
--- a/samples/Support4Demos/src/com/example/android/supportv4/media/MediaController.java
+++ b/samples/Support4Demos/src/com/example/android/supportv4/media/MediaController.java
@@ -16,6 +16,9 @@
package com.example.android.supportv4.media;
+import android.support.v4.media.TransportController;
+import android.support.v4.media.TransportMediator;
+import android.support.v4.media.TransportStateListener;
import com.example.android.supportv4.R;
import android.content.Context;
@@ -40,28 +43,38 @@
*/
public class MediaController extends FrameLayout {
- private MediaPlayerControl mPlayer;
+ private TransportController mController;
private Context mContext;
private ProgressBar mProgress;
private TextView mEndTime, mCurrentTime;
- private boolean mDragging;
- private boolean mUseFastForward;
- private boolean mFromXml;
- private boolean mListenersSet;
+ private boolean mDragging;
+ private boolean mUseFastForward;
+ private boolean mListenersSet;
+ private boolean mShowNext, mShowPrev;
private View.OnClickListener mNextListener, mPrevListener;
- StringBuilder mFormatBuilder;
+ StringBuilder mFormatBuilder;
Formatter mFormatter;
private ImageButton mPauseButton;
- private ImageButton mFfwdButton;
- private ImageButton mRewButton;
- private ImageButton mNextButton;
- private ImageButton mPrevButton;
+ private ImageButton mFfwdButton;
+ private ImageButton mRewButton;
+ private ImageButton mNextButton;
+ private ImageButton mPrevButton;
+
+ private TransportStateListener mStateListener = new TransportStateListener() {
+ @Override
+ public void onPlayingChanged(TransportController controller) {
+ updatePausePlay();
+ }
+ @Override
+ public void onTransportControlsChanged(TransportController controller) {
+ updateButtons();
+ }
+ };
public MediaController(Context context, AttributeSet attrs) {
super(context, attrs);
mContext = context;
mUseFastForward = true;
- mFromXml = true;
LayoutInflater inflate = (LayoutInflater)
mContext.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
inflate.inflate(R.layout.media_controller, this, true);
@@ -78,11 +91,35 @@
this(context, true);
}
- public void setMediaPlayer(MediaPlayerControl player) {
- mPlayer = player;
+ public void setMediaPlayer(TransportController controller) {
+ if (getWindowToken() != null) {
+ if (mController != null) {
+ mController.unregisterStateListener(mStateListener);
+ }
+ if (controller != null) {
+ controller.registerStateListener(mStateListener);
+ }
+ }
+ mController = controller;
updatePausePlay();
}
+ @Override
+ protected void onAttachedToWindow() {
+ super.onAttachedToWindow();
+ if (mController != null) {
+ mController.registerStateListener(mStateListener);
+ }
+ }
+
+ @Override
+ protected void onDetachedFromWindow() {
+ super.onDetachedFromWindow();
+ if (mController != null) {
+ mController.unregisterStateListener(mStateListener);
+ }
+ }
+
private void initControllerView() {
mPauseButton = (ImageButton) findViewById(R.id.pause);
if (mPauseButton != null) {
@@ -93,26 +130,22 @@
mFfwdButton = (ImageButton) findViewById(R.id.ffwd);
if (mFfwdButton != null) {
mFfwdButton.setOnClickListener(mFfwdListener);
- if (!mFromXml) {
- mFfwdButton.setVisibility(mUseFastForward ? View.VISIBLE : View.GONE);
- }
+ mFfwdButton.setVisibility(mUseFastForward ? View.VISIBLE : View.GONE);
}
mRewButton = (ImageButton) findViewById(R.id.rew);
if (mRewButton != null) {
mRewButton.setOnClickListener(mRewListener);
- if (!mFromXml) {
- mRewButton.setVisibility(mUseFastForward ? View.VISIBLE : View.GONE);
- }
+ mRewButton.setVisibility(mUseFastForward ? View.VISIBLE : View.GONE);
}
// By default these are hidden. They will be enabled when setPrevNextListeners() is called
mNextButton = (ImageButton) findViewById(R.id.next);
- if (mNextButton != null && !mFromXml && !mListenersSet) {
+ if (mNextButton != null && !mListenersSet) {
mNextButton.setVisibility(View.GONE);
}
mPrevButton = (ImageButton) findViewById(R.id.prev);
- if (mPrevButton != null && !mFromXml && !mListenersSet) {
+ if (mPrevButton != null && !mListenersSet) {
mPrevButton.setVisibility(View.GONE);
}
@@ -137,28 +170,34 @@
* Disable pause or seek buttons if the stream cannot be paused or seeked.
* This requires the control interface to be a MediaPlayerControlExt
*/
- private void disableUnsupportedButtons() {
- try {
- if (mPauseButton != null && !mPlayer.canPause()) {
- mPauseButton.setEnabled(false);
- }
- if (mRewButton != null && !mPlayer.canSeekBackward()) {
- mRewButton.setEnabled(false);
- }
- if (mFfwdButton != null && !mPlayer.canSeekForward()) {
- mFfwdButton.setEnabled(false);
- }
- } catch (IncompatibleClassChangeError ex) {
- // We were given an old version of the interface, that doesn't have
- // the canPause/canSeekXYZ methods. This is OK, it just means we
- // assume the media can be paused and seeked, and so we don't disable
- // the buttons.
+ void updateButtons() {
+ int flags = mController.getTransportControlFlags();
+ boolean enabled = isEnabled();
+ if (mPauseButton != null) {
+ mPauseButton.setEnabled(enabled && (flags&TransportMediator.FLAG_KEY_MEDIA_PAUSE) != 0);
+ }
+ if (mRewButton != null) {
+ mRewButton.setEnabled(enabled && (flags&TransportMediator.FLAG_KEY_MEDIA_REWIND) != 0);
+ }
+ if (mFfwdButton != null) {
+ mFfwdButton.setEnabled(enabled &&
+ (flags&TransportMediator.FLAG_KEY_MEDIA_FAST_FORWARD) != 0);
+ }
+ if (mPrevButton != null) {
+ mShowPrev = (flags&TransportMediator.FLAG_KEY_MEDIA_PREVIOUS) != 0
+ || mPrevListener != null;
+ mPrevButton.setEnabled(enabled && mShowPrev);
+ }
+ if (mNextButton != null) {
+ mShowNext = (flags&TransportMediator.FLAG_KEY_MEDIA_NEXT) != 0
+ || mNextListener != null;
+ mNextButton.setEnabled(enabled && mShowNext);
}
}
public void refresh() {
updateProgress();
- disableUnsupportedButtons();
+ updateButtons();
updatePausePlay();
}
@@ -178,18 +217,18 @@
}
public int updateProgress() {
- if (mPlayer == null || mDragging) {
+ if (mController == null || mDragging) {
return 0;
}
- int position = mPlayer.getCurrentPosition();
- int duration = mPlayer.getDuration();
+ int position = mController.getCurrentPosition();
+ int duration = mController.getDuration();
if (mProgress != null) {
if (duration > 0) {
// use long to avoid overflow
long pos = 1000L * position / duration;
mProgress.setProgress( (int) pos);
}
- int percent = mPlayer.getBufferPercentage();
+ int percent = mController.getBufferPercentage();
mProgress.setSecondaryProgress(percent * 10);
}
@@ -211,7 +250,7 @@
if (mPauseButton == null)
return;
- if (mPlayer.isPlaying()) {
+ if (mController.isPlaying()) {
mPauseButton.setImageResource(android.R.drawable.ic_media_pause);
} else {
mPauseButton.setImageResource(android.R.drawable.ic_media_play);
@@ -219,10 +258,10 @@
}
private void doPauseResume() {
- if (mPlayer.isPlaying()) {
- mPlayer.pause();
+ if (mController.isPlaying()) {
+ mController.pausePlaying();
} else {
- mPlayer.start();
+ mController.startPlaying();
}
updatePausePlay();
}
@@ -250,9 +289,9 @@
return;
}
- long duration = mPlayer.getDuration();
+ long duration = mController.getDuration();
long newposition = (duration * progress) / 1000L;
- mPlayer.seekTo( (int) newposition);
+ mController.seekTo((int) newposition);
if (mCurrentTime != null)
mCurrentTime.setText(stringForTime( (int) newposition));
}
@@ -266,26 +305,8 @@
@Override
public void setEnabled(boolean enabled) {
- if (mPauseButton != null) {
- mPauseButton.setEnabled(enabled);
- }
- if (mFfwdButton != null) {
- mFfwdButton.setEnabled(enabled);
- }
- if (mRewButton != null) {
- mRewButton.setEnabled(enabled);
- }
- if (mNextButton != null) {
- mNextButton.setEnabled(enabled && mNextListener != null);
- }
- if (mPrevButton != null) {
- mPrevButton.setEnabled(enabled && mPrevListener != null);
- }
- if (mProgress != null) {
- mProgress.setEnabled(enabled);
- }
- disableUnsupportedButtons();
super.setEnabled(enabled);
+ updateButtons();
}
@Override
@@ -302,18 +323,18 @@
private View.OnClickListener mRewListener = new View.OnClickListener() {
public void onClick(View v) {
- int pos = mPlayer.getCurrentPosition();
+ int pos = mController.getCurrentPosition();
pos -= 5000; // milliseconds
- mPlayer.seekTo(pos);
+ mController.seekTo(pos);
updateProgress();
}
};
private View.OnClickListener mFfwdListener = new View.OnClickListener() {
public void onClick(View v) {
- int pos = mPlayer.getCurrentPosition();
+ int pos = mController.getCurrentPosition();
pos += 15000; // milliseconds
- mPlayer.seekTo(pos);
+ mController.seekTo(pos);
updateProgress();
}
};
@@ -321,12 +342,12 @@
private void installPrevNextListeners() {
if (mNextButton != null) {
mNextButton.setOnClickListener(mNextListener);
- mNextButton.setEnabled(mNextListener != null);
+ mNextButton.setEnabled(mShowNext);
}
if (mPrevButton != null) {
mPrevButton.setOnClickListener(mPrevListener);
- mPrevButton.setEnabled(mPrevListener != null);
+ mPrevButton.setEnabled(mShowPrev);
}
}
@@ -337,24 +358,13 @@
installPrevNextListeners();
- if (mNextButton != null && !mFromXml) {
+ if (mNextButton != null) {
mNextButton.setVisibility(View.VISIBLE);
+ mShowNext = true;
}
- if (mPrevButton != null && !mFromXml) {
+ if (mPrevButton != null) {
mPrevButton.setVisibility(View.VISIBLE);
+ mShowPrev = true;
}
}
-
- public interface MediaPlayerControl {
- void start();
- void pause();
- int getDuration();
- int getCurrentPosition();
- void seekTo(int pos);
- boolean isPlaying();
- int getBufferPercentage();
- boolean canPause();
- boolean canSeekBackward();
- boolean canSeekForward();
- }
}
diff --git a/samples/Support4Demos/src/com/example/android/supportv4/media/TransportControllerActivity.java b/samples/Support4Demos/src/com/example/android/supportv4/media/TransportControllerActivity.java
index a4e0951..0041aa2 100644
--- a/samples/Support4Demos/src/com/example/android/supportv4/media/TransportControllerActivity.java
+++ b/samples/Support4Demos/src/com/example/android/supportv4/media/TransportControllerActivity.java
@@ -16,6 +16,8 @@
package com.example.android.supportv4.media;
+import android.support.v4.media.TransportMediator;
+import android.support.v4.media.TransportPerformer;
import com.example.android.supportv4.R;
import android.app.ActionBar;
@@ -31,8 +33,6 @@
import android.os.Bundle;
import android.widget.VideoView;
-import android.support.v4.media.TransportController;
-
public class TransportControllerActivity extends Activity {
/**
@@ -40,92 +40,70 @@
* file path.
*/
private Content mContent;
- private TransportController mTransportController;
+ private TransportMediator mTransportMediator;
private MediaController mMediaController;
/**
- * Handle media buttons to start/stop video playback. Real implementations
- * will probably handle more buttons, like skip and fast-forward.
- */
- TransportController.Callbacks mTransportCallbacks = new TransportController.Callbacks() {
- public boolean onMediaButtonDown(int keyCode, KeyEvent event) {
- switch (keyCode) {
- case TransportController.KEYCODE_MEDIA_PLAY:
- mMediaPlayerControl.start();
- return true;
- case TransportController.KEYCODE_MEDIA_PAUSE:
- case KeyEvent.KEYCODE_MEDIA_STOP:
- mMediaPlayerControl.pause();
- return true;
- case KeyEvent.KEYCODE_MEDIA_PLAY_PAUSE:
- case KeyEvent.KEYCODE_HEADSETHOOK:
- if (mContent.isPlaying()) {
- mMediaPlayerControl.pause();
- } else {
- mMediaPlayerControl.start();
- }
- }
- return true;
- }
- };
-
- /**
* Handle actions from on-screen media controls. Most of these are simple re-directs
* to the VideoView; some we need to capture to update our state.
*/
- MediaController.MediaPlayerControl mMediaPlayerControl
- = new MediaController.MediaPlayerControl() {
+ TransportPerformer mTransportPerformer = new TransportPerformer() {
@Override
- public void start() {
- mTransportController.startPlaying();
+ public void onStart() {
mContent.start();
}
@Override
- public void pause() {
- mTransportController.pausePlaying();
+ public void onStop() {
mContent.pause();
}
@Override
- public int getDuration() {
+ public void onPause() {
+ mContent.pause();
+ }
+
+ @Override
+ public int onGetDuration() {
return mContent.getDuration();
}
@Override
- public int getCurrentPosition() {
+ public int onGetCurrentPosition() {
return mContent.getCurrentPosition();
}
@Override
- public void seekTo(int pos) {
+ public void onSeekTo(int pos) {
mContent.seekTo(pos);
}
@Override
- public boolean isPlaying() {
+ public boolean onIsPlaying() {
return mContent.isPlaying();
}
@Override
- public int getBufferPercentage() {
+ public int onGetBufferPercentage() {
return mContent.getBufferPercentage();
}
@Override
- public boolean canPause() {
- return mContent.canPause();
- }
-
- @Override
- public boolean canSeekBackward() {
- return mContent.canSeekBackward();
- }
-
- @Override
- public boolean canSeekForward() {
- return mContent.canSeekForward();
+ public int onGetTransportControlFlags() {
+ int flags = TransportMediator.FLAG_KEY_MEDIA_PLAY
+ | TransportMediator.FLAG_KEY_MEDIA_PLAY_PAUSE
+ | TransportMediator.FLAG_KEY_MEDIA_STOP;
+ if (mContent.canPause()) {
+ flags |= TransportMediator.FLAG_KEY_MEDIA_PAUSE;
+ }
+ if (mContent.canSeekBackward()) {
+ flags |= TransportMediator.FLAG_KEY_MEDIA_REWIND;
+ }
+ if (mContent.canSeekForward()) {
+ flags |= TransportMediator.FLAG_KEY_MEDIA_FAST_FORWARD;
+ }
+ return flags;
}
};
@@ -139,7 +117,7 @@
ActionBar.OnMenuVisibilityListener, MediaPlayer.OnPreparedListener,
MediaPlayer.OnCompletionListener, MediaPlayer.OnErrorListener {
Activity mActivity;
- TransportController mTransportController;
+ TransportMediator mTransportMediator;
MediaController mMediaController;
boolean mAddedMenuListener;
boolean mMenusOpen;
@@ -169,12 +147,12 @@
setOnErrorListener(this);
}
- public void init(Activity activity, TransportController transportController,
+ public void init(Activity activity, TransportMediator transportMediator,
MediaController mediaController) {
// This called by the containing activity to supply the surrounding
// state of the video player that it will interact with.
mActivity = activity;
- mTransportController = transportController;
+ mTransportMediator = transportMediator;
mMediaController = mediaController;
pause();
}
@@ -231,13 +209,13 @@
@Override
public void onCompletion(MediaPlayer mp) {
- mTransportController.pausePlaying();
+ mTransportMediator.pausePlaying();
pause();
}
@Override
public boolean onError(MediaPlayer mp, int what, int extra) {
- mTransportController.pausePlaying();
+ mTransportMediator.pausePlaying();
pause();
return false;
}
@@ -309,16 +287,16 @@
// Find the video player in our UI.
mContent = (Content) findViewById(R.id.content);
- // Create and initialize the media control UI.
- mMediaController = (MediaController) findViewById(R.id.media_controller);
- mMediaController.setMediaPlayer(mMediaPlayerControl);
-
// Create transport controller to control video, giving the callback
// interface to receive actions from.
- mTransportController = new TransportController(this, mTransportCallbacks);
+ mTransportMediator = new TransportMediator(this, mTransportPerformer);
+
+ // Create and initialize the media control UI.
+ mMediaController = (MediaController) findViewById(R.id.media_controller);
+ mMediaController.setMediaPlayer(mTransportMediator);
// We're just playing a built-in demo video.
- mContent.init(this, mTransportController, mMediaController);
+ mContent.init(this, mTransportMediator, mMediaController);
mContent.setVideoURI(Uri.parse("android.resource://" + getPackageName() +
"/" + R.raw.videoviewdemo));
}
@@ -328,7 +306,7 @@
// We first dispatch keys to the transport controller -- we want it
// to get to consume any media keys rather than letting whoever has focus
// in the view hierarchy to potentially eat it.
- if (mTransportController.dispatchKeyEvent(event)) {
+ if (mTransportMediator.dispatchKeyEvent(event)) {
return true;
}