From: David A. Velasco Date: Mon, 11 Mar 2013 09:20:04 +0000 (+0100) Subject: Improving our own media control: removed 'next' and 'previous' buttons, removed undes... X-Git-Tag: oc-android-1.4.3~39^2~17 X-Git-Url: http://git.linex4red.de/pub/Android/ownCloud.git/commitdiff_plain/ca8a19850b253312ad792170f09fe0b436cbb125 Improving our own media control: removed 'next' and 'previous' buttons, removed undesired 'show' and 'hide' behaviour, fixed update of progress bar, recovered BACK button --- diff --git a/res/layout/media_control.xml b/res/layout/media_control.xml index 69d27c66..070ae8c7 100644 --- a/res/layout/media_control.xml +++ b/res/layout/media_control.xml @@ -33,11 +33,6 @@ > - - diff --git a/src/com/owncloud/android/media/MediaControlView.java b/src/com/owncloud/android/media/MediaControlView.java index cb9ea19e..9db76df5 100644 --- a/src/com/owncloud/android/media/MediaControlView.java +++ b/src/com/owncloud/android/media/MediaControlView.java @@ -19,23 +19,15 @@ package com.owncloud.android.media; import android.content.Context; -import android.graphics.PixelFormat; -import android.media.AudioManager; import android.media.MediaPlayer; import android.os.Handler; import android.os.Message; import android.util.AttributeSet; -import android.util.Log; -import android.view.Gravity; import android.view.KeyEvent; import android.view.LayoutInflater; -import android.view.MotionEvent; import android.view.View; -import android.view.View.OnLayoutChangeListener; -import android.view.View.OnTouchListener; +import android.view.View.OnClickListener; import android.view.ViewGroup; -import android.view.Window; -import android.view.WindowManager; import android.view.accessibility.AccessibilityEvent; import android.view.accessibility.AccessibilityNodeInfo; import android.widget.FrameLayout; @@ -63,52 +55,29 @@ import com.owncloud.android.R; * @author David A. Velasco */ -public class MediaControlView extends FrameLayout implements /* OnLayoutChangeListener, */ OnTouchListener { +public class MediaControlView extends FrameLayout /* implements OnLayoutChangeListener, OnTouchListener */ implements OnClickListener, OnSeekBarChangeListener { - private static final String TAG = MediaControlView.class.getSimpleName(); - - private MediaPlayerControl mPlayer; private Context mContext; - private View mAnchor; private View mRoot; - private WindowManager mWindowManager; - //private Window mWindow; - private View mDecor; - private WindowManager.LayoutParams mDecorLayoutParams; private ProgressBar mProgress; private TextView mEndTime, mCurrentTime; - private boolean mShowing; private boolean mDragging; - private static final int sDefaultTimeout = 3000; - private static final int FADE_OUT = 1; - private static final int SHOW_PROGRESS = 2; - private boolean mUseFastForward; - private boolean mFromXml; - private boolean mListenersSet; - private View.OnClickListener mNextListener, mPrevListener; + private static final int SHOW_PROGRESS = 1; StringBuilder mFormatBuilder; Formatter mFormatter; private ImageButton mPauseButton; private ImageButton mFfwdButton; private ImageButton mRewButton; - private ImageButton mNextButton; - private ImageButton mPrevButton; public MediaControlView(Context context, AttributeSet attrs) { super(context, attrs); - //mRoot = this; // TODO review if this is adequate mContext = context; - mUseFastForward = true; - mFromXml = true; - - mWindowManager = (WindowManager)mContext.getSystemService(Context.WINDOW_SERVICE); FrameLayout.LayoutParams frameParams = new FrameLayout.LayoutParams( ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT ); - //removeAllViews(); LayoutInflater inflate = (LayoutInflater) mContext.getSystemService(Context.LAYOUT_INFLATER_SERVICE); mRoot = inflate.inflate(R.layout.media_control, null); initControllerView(mRoot); @@ -122,8 +91,10 @@ public class MediaControlView extends FrameLayout implements /* OnLayoutChangeLi @Override public void onFinishInflate() { + /* if (mRoot != null) initControllerView(mRoot); + */ } /* TODO REMOVE @@ -186,6 +157,7 @@ public class MediaControlView extends FrameLayout implements /* OnLayoutChangeLi // Update the dynamic parts of mDecorLayoutParams // Must be called with mAnchor != NULL. + /* private void updateFloatingWindowLayout() { int [] anchorPos = new int[2]; mAnchor.getLocationOnScreen(anchorPos); @@ -194,6 +166,7 @@ public class MediaControlView extends FrameLayout implements /* OnLayoutChangeLi p.width = mAnchor.getWidth(); p.y = anchorPos[1] + mAnchor.getHeight(); } + */ /* // This is called whenever mAnchor's layout bound changes @@ -207,6 +180,7 @@ public class MediaControlView extends FrameLayout implements /* OnLayoutChangeLi } */ + /* public boolean onTouch(View v, MotionEvent event) { if (event.getAction() == MotionEvent.ACTION_DOWN) { if (mShowing) { @@ -215,94 +189,38 @@ public class MediaControlView extends FrameLayout implements /* OnLayoutChangeLi } return false; } + */ public void setMediaPlayer(MediaPlayerControl player) { mPlayer = player; + mHandler.sendEmptyMessage(SHOW_PROGRESS); updatePausePlay(); } - /* - /** - * Set the view that acts as the anchor for the control view. - * This can for example be a VideoView, or your Activity's main view. - * @param view The view to which to anchor the controller when it is visible. - *-/ - public void setAnchorView(View view) { - if (mAnchor != null) { - mAnchor.removeOnLayoutChangeListener(this); - } - mAnchor = view; - if (mAnchor != null) { - mAnchor.addOnLayoutChangeListener(this); - } - - FrameLayout.LayoutParams frameParams = new FrameLayout.LayoutParams( - ViewGroup.LayoutParams.MATCH_PARENT, - ViewGroup.LayoutParams.MATCH_PARENT - ); - - removeAllViews(); - View v = makeControllerView(); - addView(v, frameParams); - } - */ - /* - /** - * Create the view that holds the widgets that control playback. - * Derived classes can override this to create their own. - * @return The controller view. - * @hide This doesn't work as advertised - *-/ - protected View makeControllerView() { - LayoutInflater inflate = (LayoutInflater) mContext.getSystemService(Context.LAYOUT_INFLATER_SERVICE); - mRoot = inflate.inflate(R.layout.media_control, null); - - initControllerView(mRoot); - - return mRoot; - } - */ - private void initControllerView(View v) { mPauseButton = (ImageButton) v.findViewById(R.id.playBtn); if (mPauseButton != null) { mPauseButton.requestFocus(); - mPauseButton.setOnClickListener(mPauseListener); + mPauseButton.setOnClickListener(this); } mFfwdButton = (ImageButton) v.findViewById(R.id.forwardBtn); if (mFfwdButton != null) { - mFfwdButton.setOnClickListener(mFfwdListener); - if (!mFromXml) { - mFfwdButton.setVisibility(mUseFastForward ? View.VISIBLE : View.GONE); - } + mFfwdButton.setOnClickListener(this); } mRewButton = (ImageButton) v.findViewById(R.id.rewindBtn); if (mRewButton != null) { - mRewButton.setOnClickListener(mRewListener); - if (!mFromXml) { - mRewButton.setVisibility(mUseFastForward ? View.VISIBLE : View.GONE); - } - } - - // By default these are hidden. They will be enabled when setPrevNextListeners() is called - mNextButton = (ImageButton) v.findViewById(R.id.nextBtn); - if (mNextButton != null && !mFromXml && !mListenersSet) { - mNextButton.setVisibility(View.GONE); - } - mPrevButton = (ImageButton) v.findViewById(R.id.previousBtn); - if (mPrevButton != null && !mFromXml && !mListenersSet) { - mPrevButton.setVisibility(View.GONE); + mRewButton.setOnClickListener(this); } mProgress = (ProgressBar) v.findViewById(R.id.progressBar); if (mProgress != null) { if (mProgress instanceof SeekBar) { SeekBar seeker = (SeekBar) mProgress; - seeker.setOnSeekBarChangeListener(mSeekListener); + seeker.setOnSeekBarChangeListener(this); } mProgress.setMax(1000); } @@ -312,17 +230,9 @@ public class MediaControlView extends FrameLayout implements /* OnLayoutChangeLi mFormatBuilder = new StringBuilder(); mFormatter = new Formatter(mFormatBuilder, Locale.getDefault()); - installPrevNextListeners(); - } - - /** - * Show the controller on screen. It will go away - * automatically after 3 seconds of inactivity. - */ - public void show() { - show(sDefaultTimeout); } + /** * Disable pause or seek buttons if the stream cannot be paused or seeked. * This requires the control interface to be a MediaPlayerControlExt @@ -346,72 +256,15 @@ public class MediaControlView extends FrameLayout implements /* OnLayoutChangeLi } } - /** - * Show the controller on screen. It will go away - * automatically after 'timeout' milliseconds of inactivity. - * @param timeout The timeout in milliseconds. Use 0 to show - * the controller until hide() is called. - */ - public void show(int timeout) { - if (!mShowing && mAnchor != null) { - setProgress(); - if (mPauseButton != null) { - mPauseButton.requestFocus(); - } - disableUnsupportedButtons(); - //updateFloatingWindowLayout(); - mWindowManager.addView(mDecor, mDecorLayoutParams); - mShowing = true; - } - updatePausePlay(); - - // cause the progress bar to be updated even if mShowing - // was already true. This happens, for example, if we're - // paused with the progress bar showing the user hits play. - mHandler.sendEmptyMessage(SHOW_PROGRESS); - - Message msg = mHandler.obtainMessage(FADE_OUT); - if (timeout != 0) { - mHandler.removeMessages(FADE_OUT); - mHandler.sendMessageDelayed(msg, timeout); - } - } - public boolean isShowing() { - return mShowing; - } - - /** - * Remove the controller from the screen. - */ - public void hide() { - /* - if (mAnchor == null) - return; - - if (mShowing) { - try { - mHandler.removeMessages(SHOW_PROGRESS); - mWindowManager.removeView(mDecor); - } catch (IllegalArgumentException ex) { - Log.w(TAG, "already removed"); - } - mShowing = false; - } - */ - } - private Handler mHandler = new Handler() { @Override public void handleMessage(Message msg) { int pos; switch (msg.what) { - case FADE_OUT: - hide(); - break; case SHOW_PROGRESS: pos = setProgress(); - if (!mDragging && mShowing && mPlayer.isPlaying()) { + if (!mDragging) { msg = obtainMessage(SHOW_PROGRESS); sendMessageDelayed(msg, 1000 - (pos % 1000)); } @@ -458,18 +311,7 @@ public class MediaControlView extends FrameLayout implements /* OnLayoutChangeLi return position; } - - @Override - public boolean onTouchEvent(MotionEvent event) { - show(sDefaultTimeout); - return true; - } - - @Override - public boolean onTrackballEvent(MotionEvent ev) { - show(sDefaultTimeout); - return false; - } + @Override public boolean dispatchKeyEvent(KeyEvent event) { @@ -481,7 +323,7 @@ public class MediaControlView extends FrameLayout implements /* OnLayoutChangeLi || keyCode == KeyEvent.KEYCODE_SPACE) { if (uniqueDown) { doPauseResume(); - show(sDefaultTimeout); + //show(sDefaultTimeout); if (mPauseButton != null) { mPauseButton.requestFocus(); } @@ -491,7 +333,7 @@ public class MediaControlView extends FrameLayout implements /* OnLayoutChangeLi if (uniqueDown && !mPlayer.isPlaying()) { mPlayer.start(); updatePausePlay(); - show(sDefaultTimeout); + //show(sDefaultTimeout); } return true; } else if (keyCode == KeyEvent.KEYCODE_MEDIA_STOP @@ -499,34 +341,16 @@ public class MediaControlView extends FrameLayout implements /* OnLayoutChangeLi if (uniqueDown && mPlayer.isPlaying()) { mPlayer.pause(); updatePausePlay(); - show(sDefaultTimeout); - } - return true; - } else if (keyCode == KeyEvent.KEYCODE_VOLUME_DOWN - || keyCode == KeyEvent.KEYCODE_VOLUME_UP - || keyCode == KeyEvent.KEYCODE_VOLUME_MUTE - || keyCode == KeyEvent.KEYCODE_CAMERA) { - // don't show the controls for volume adjustment - return super.dispatchKeyEvent(event); - } else if (keyCode == KeyEvent.KEYCODE_BACK || keyCode == KeyEvent.KEYCODE_MENU) { - if (uniqueDown) { - hide(); + //show(sDefaultTimeout); } return true; } - show(sDefaultTimeout); + //show(sDefaultTimeout); return super.dispatchKeyEvent(event); } - private View.OnClickListener mPauseListener = new View.OnClickListener() { - public void onClick(View v) { - doPauseResume(); - show(sDefaultTimeout); - } - }; - - private void updatePausePlay() { + public void updatePausePlay() { if (mRoot == null || mPauseButton == null) return; @@ -546,58 +370,6 @@ public class MediaControlView extends FrameLayout implements /* OnLayoutChangeLi updatePausePlay(); } - // There are two scenarios that can trigger the seekbar listener to trigger: - // - // The first is the user using the touchpad to adjust the posititon of the - // seekbar's thumb. In this case onStartTrackingTouch is called followed by - // a number of onProgressChanged notifications, concluded by onStopTrackingTouch. - // We're setting the field "mDragging" to true for the duration of the dragging - // session to avoid jumps in the position in case of ongoing playback. - // - // The second scenario involves the user operating the scroll ball, in this - // case there WON'T BE onStartTrackingTouch/onStopTrackingTouch notifications, - // we will simply apply the updated position without suspending regular updates. - private OnSeekBarChangeListener mSeekListener = new OnSeekBarChangeListener() { - public void onStartTrackingTouch(SeekBar bar) { - show(3600000); - - mDragging = true; - - // By removing these pending progress messages we make sure - // that a) we won't update the progress while the user adjusts - // the seekbar and b) once the user is done dragging the thumb - // we will post one of these messages to the queue again and - // this ensures that there will be exactly one message queued up. - mHandler.removeMessages(SHOW_PROGRESS); - } - - public void onProgressChanged(SeekBar bar, int progress, boolean fromuser) { - if (!fromuser) { - // We're not interested in programmatically generated changes to - // the progress bar's position. - return; - } - - long duration = mPlayer.getDuration(); - long newposition = (duration * progress) / 1000L; - mPlayer.seekTo( (int) newposition); - if (mCurrentTime != null) - mCurrentTime.setText(stringForTime( (int) newposition)); - } - - public void onStopTrackingTouch(SeekBar bar) { - mDragging = false; - setProgress(); - updatePausePlay(); - show(sDefaultTimeout); - - // Ensure that progress is properly updated in the future, - // the call to show() does not guarantee this because it is a - // no-op if we are already showing. - mHandler.sendEmptyMessage(SHOW_PROGRESS); - } - }; - @Override public void setEnabled(boolean enabled) { if (mPauseButton != null) { @@ -609,12 +381,6 @@ public class MediaControlView extends FrameLayout implements /* OnLayoutChangeLi 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); } @@ -623,66 +389,82 @@ public class MediaControlView extends FrameLayout implements /* OnLayoutChangeLi } @Override - public void onInitializeAccessibilityEvent(AccessibilityEvent event) { - super.onInitializeAccessibilityEvent(event); - event.setClassName(MediaControlView.class.getName()); - } - - @Override - public void onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo info) { - super.onInitializeAccessibilityNodeInfo(info); - info.setClassName(MediaControlView.class.getName()); - } + public void onClick(View v) { + int pos; + switch (v.getId()) { + + case R.id.playBtn: + doPauseResume(); + break; - private View.OnClickListener mRewListener = new View.OnClickListener() { - public void onClick(View v) { - int pos = mPlayer.getCurrentPosition(); - pos -= 5000; // milliseconds + case R.id.rewindBtn: + pos = mPlayer.getCurrentPosition(); + pos -= 5000; mPlayer.seekTo(pos); setProgress(); + break; - show(sDefaultTimeout); - } - }; - - private View.OnClickListener mFfwdListener = new View.OnClickListener() { - public void onClick(View v) { - int pos = mPlayer.getCurrentPosition(); - pos += 15000; // milliseconds + case R.id.forwardBtn: + pos = mPlayer.getCurrentPosition(); + pos += 15000; mPlayer.seekTo(pos); setProgress(); - - show(sDefaultTimeout); + break; + } - }; - - private void installPrevNextListeners() { - if (mNextButton != null) { - mNextButton.setOnClickListener(mNextListener); - mNextButton.setEnabled(mNextListener != null); + } + + + @Override + public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) { + if (!fromUser) { + // We're not interested in programmatically generated changes to + // the progress bar's position. + return; } - if (mPrevButton != null) { - mPrevButton.setOnClickListener(mPrevListener); - mPrevButton.setEnabled(mPrevListener != null); - } + long duration = mPlayer.getDuration(); + long newposition = (duration * progress) / 1000L; + mPlayer.seekTo( (int) newposition); + if (mCurrentTime != null) + mCurrentTime.setText(stringForTime( (int) newposition)); + } + + /** + * Called in devices with touchpad when the user starts to adjust the + * position of the seekbar's thumb. + * + * Will be followed by several onProgressChanged notifications. + */ + @Override + public void onStartTrackingTouch(SeekBar seekBar) { + mDragging = true; // monitors the duration of dragging + mHandler.removeMessages(SHOW_PROGRESS); // grants no more updates with media player progress while dragging } - public void setPrevNextListeners(View.OnClickListener next, View.OnClickListener prev) { - mNextListener = next; - mPrevListener = prev; - mListenersSet = true; + + /** + * Called in devices with touchpad when the user finishes the + * adjusting of the seekbar. + */ + @Override + public void onStopTrackingTouch(SeekBar seekBar) { + mDragging = false; + setProgress(); + updatePausePlay(); + mHandler.sendEmptyMessage(SHOW_PROGRESS); // grants future updates with media player progress + } - if (mRoot != null) { - installPrevNextListeners(); - - if (mNextButton != null && !mFromXml) { - mNextButton.setVisibility(View.VISIBLE); - } - if (mPrevButton != null && !mFromXml) { - mPrevButton.setVisibility(View.VISIBLE); - } - } + @Override + public void onInitializeAccessibilityEvent(AccessibilityEvent event) { + super.onInitializeAccessibilityEvent(event); + event.setClassName(MediaControlView.class.getName()); } + @Override + public void onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo info) { + super.onInitializeAccessibilityNodeInfo(info); + info.setClassName(MediaControlView.class.getName()); + } + } diff --git a/src/com/owncloud/android/ui/preview/PreviewMediaFragment.java b/src/com/owncloud/android/ui/preview/PreviewMediaFragment.java index f9fd122e..cee0c609 100644 --- a/src/com/owncloud/android/ui/preview/PreviewMediaFragment.java +++ b/src/com/owncloud/android/ui/preview/PreviewMediaFragment.java @@ -329,18 +329,13 @@ public class PreviewMediaFragment extends SherlockFragment implements } private void playVideo() { + // create and prepare control panel for the user + mMediaController.setMediaPlayer(mVideoPreview); + // load the video file in the video player ; when done, VideoHelper#onPrepared() will be called mVideoPreview.setVideoPath(mFile.getStoragePath()); - // create and prepare control panel for the user - //mMediaController = new MediaController(getActivity()); - if (mMediaController != null) { - mMediaController.setMediaPlayer(mVideoPreview); - //mMediaController.setAnchorView(mVideoPreview); - //mVideoPreview.setMediaController(mMediaController); - } else { - Toast.makeText(getActivity(), "No media controller to play video", Toast.LENGTH_SHORT).show(); - } + //mVideoPreview.setMediaController(mMediaController); } @@ -357,6 +352,8 @@ public class PreviewMediaFragment extends SherlockFragment implements public void onPrepared(MediaPlayer vp) { mVideoPreview.seekTo(mSavedPlaybackPosition); mVideoPreview.start(); + mMediaController.setEnabled(true); + mMediaController.updatePausePlay(); //mMediaController.show(MediaService.MEDIA_CONTROL_SHORT_LIFE); } @@ -486,6 +483,7 @@ public class PreviewMediaFragment extends SherlockFragment implements if (!mMediaServiceBinder.isPlaying()) { mMediaServiceBinder.start(); } + /* if (!mMediaController.isShowing() && isVisible()) { //mMediaController.show(MediaService.MEDIA_CONTROL_PERMANENT); // TODO - fix strange bug; steps to trigger : @@ -495,6 +493,7 @@ public class PreviewMediaFragment extends SherlockFragment implements // 4. go to notification bar and click on the "ownCloud music app" notification // PUM! } + */ } } @@ -540,10 +539,8 @@ public class PreviewMediaFragment extends SherlockFragment implements //mMediaServiceBinder.registerMediaController(mMediaController); if (mMediaController != null) { mMediaController.setMediaPlayer(mMediaServiceBinder); - //mMediaController.setAnchorView(getView()); - mMediaController.setEnabled(mMediaServiceBinder.isInPlaybackState()); - } else { - Toast.makeText(getActivity(), "No media controller to prepare when connected to media service", Toast.LENGTH_SHORT).show(); + mMediaController.setEnabled(true); + mMediaController.updatePausePlay(); } }