From: David A. Velasco Date: Fri, 8 Mar 2013 12:32:10 +0000 (+0100) Subject: Create our own media control - basic operation X-Git-Tag: oc-android-1.4.3~39^2~18 X-Git-Url: http://git.linex4red.de/pub/Android/ownCloud.git/commitdiff_plain/d68b32465328dafb0cd30d8104ef8a3a05ef7bde?hp=--cc Create our own media control - basic operation --- d68b32465328dafb0cd30d8104ef8a3a05ef7bde diff --git a/res/layout/file_preview.xml b/res/layout/file_preview.xml index e18aa403..85d1856e 100644 --- a/res/layout/file_preview.xml +++ b/res/layout/file_preview.xml @@ -19,36 +19,46 @@ --> - - - + - + + + + + + + \ No newline at end of file diff --git a/res/layout/media_control.xml b/res/layout/media_control.xml new file mode 100644 index 00000000..69d27c66 --- /dev/null +++ b/res/layout/media_control.xml @@ -0,0 +1,104 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/res/values/strings.xml b/res/values/strings.xml index cdbd6eea..5b834a9b 100644 --- a/res/values/strings.xml +++ b/res/values/strings.xml @@ -89,7 +89,7 @@ Leave %1$s Error Loading … - Unkown error + Unknown error About Delete account @@ -162,7 +162,12 @@ Security error trying to play %1$s Input error trying to play %1$s Unexpected error tryung to playe %1$s - + Previous track button + Rewind button + Play or pause button + Fast forward button + Next track button + 15 Minutes 30 Minutes @@ -267,6 +272,7 @@ PNG Image 389 KB 2012/05/18 12:23 PM + 12:23:45 Upload pictures via WiFi only /InstantUpload diff --git a/src/com/owncloud/android/media/MediaControlView.java b/src/com/owncloud/android/media/MediaControlView.java new file mode 100644 index 00000000..cb9ea19e --- /dev/null +++ b/src/com/owncloud/android/media/MediaControlView.java @@ -0,0 +1,688 @@ +/* ownCloud Android client application + * + * Copyright (C) 2012-2013 ownCloud Inc. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + */ +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.ViewGroup; +import android.view.Window; +import android.view.WindowManager; +import android.view.accessibility.AccessibilityEvent; +import android.view.accessibility.AccessibilityNodeInfo; +import android.widget.FrameLayout; +import android.widget.ImageButton; +import android.widget.MediaController.MediaPlayerControl; +import android.widget.ProgressBar; +import android.widget.SeekBar; +import android.widget.SeekBar.OnSeekBarChangeListener; +import android.widget.TextView; + +import java.util.Formatter; +import java.util.Locale; + +import com.owncloud.android.R; + +/** + * View containing controls for a {@link MediaPlayer}. + * + * Holds buttons "play / pause", "rewind", "fast forward" + * and a progress slider. + * + * It synchronizes itself with the state of the + * {@link MediaPlayer}. + * + * @author David A. Velasco + */ + +public class MediaControlView extends FrameLayout implements /* OnLayoutChangeListener, */ OnTouchListener { + + 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; + 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); + addView(mRoot, frameParams); + + setFocusable(true); + setFocusableInTouchMode(true); + setDescendantFocusability(ViewGroup.FOCUS_AFTER_DESCENDANTS); + requestFocus(); + } + + @Override + public void onFinishInflate() { + if (mRoot != null) + initControllerView(mRoot); + } + + /* TODO REMOVE + public MediaControlView(Context context, boolean useFastForward) { + super(context); + mContext = context; + mUseFastForward = useFastForward; + initFloatingWindowLayout(); + //initFloatingWindow(); + } + */ + + /* TODO REMOVE + public MediaControlView(Context context) { + this(context, true); + } + */ + + /* T + private void initFloatingWindow() { + mWindowManager = (WindowManager)mContext.getSystemService(Context.WINDOW_SERVICE); + mWindow = PolicyManager.makeNewWindow(mContext); + mWindow.setWindowManager(mWindowManager, null, null); + mWindow.requestFeature(Window.FEATURE_NO_TITLE); + mDecor = mWindow.getDecorView(); + mDecor.setOnTouchListener(mTouchListener); + mWindow.setContentView(this); + mWindow.setBackgroundDrawableResource(android.R.color.transparent); + + // While the media controller is up, the volume control keys should + // affect the media stream type + mWindow.setVolumeControlStream(AudioManager.STREAM_MUSIC); + + setFocusable(true); + setFocusableInTouchMode(true); + setDescendantFocusability(ViewGroup.FOCUS_AFTER_DESCENDANTS); + requestFocus(); + } + */ + + /* + // Allocate and initialize the static parts of mDecorLayoutParams. Must + // also call updateFloatingWindowLayout() to fill in the dynamic parts + // (y and width) before mDecorLayoutParams can be used. + private void initFloatingWindowLayout() { + mDecorLayoutParams = new WindowManager.LayoutParams(); + WindowManager.LayoutParams p = mDecorLayoutParams; + p.gravity = Gravity.TOP; + p.height = LayoutParams.WRAP_CONTENT; + p.x = 0; + p.format = PixelFormat.TRANSLUCENT; + p.type = WindowManager.LayoutParams.TYPE_APPLICATION_PANEL; + p.flags |= WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM + | WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL + | WindowManager.LayoutParams.FLAG_SPLIT_TOUCH; + p.token = null; + p.windowAnimations = 0; // android.R.style.DropDownAnimationDown; + } + */ + + // Update the dynamic parts of mDecorLayoutParams + // Must be called with mAnchor != NULL. + private void updateFloatingWindowLayout() { + int [] anchorPos = new int[2]; + mAnchor.getLocationOnScreen(anchorPos); + + WindowManager.LayoutParams p = mDecorLayoutParams; + p.width = mAnchor.getWidth(); + p.y = anchorPos[1] + mAnchor.getHeight(); + } + + /* + // This is called whenever mAnchor's layout bound changes + public void onLayoutChange(View v, int left, int top, int right, + int bottom, int oldLeft, int oldTop, int oldRight, + int oldBottom) { + //updateFloatingWindowLayout(); + if (mShowing) { + mWindowManager.updateViewLayout(mDecor, mDecorLayoutParams); + } + } + */ + + public boolean onTouch(View v, MotionEvent event) { + if (event.getAction() == MotionEvent.ACTION_DOWN) { + if (mShowing) { + hide(); + } + } + return false; + } + + + public void setMediaPlayer(MediaPlayerControl player) { + mPlayer = player; + 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); + } + + mFfwdButton = (ImageButton) v.findViewById(R.id.forwardBtn); + if (mFfwdButton != null) { + mFfwdButton.setOnClickListener(mFfwdListener); + if (!mFromXml) { + mFfwdButton.setVisibility(mUseFastForward ? View.VISIBLE : View.GONE); + } + } + + 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); + } + + mProgress = (ProgressBar) v.findViewById(R.id.progressBar); + if (mProgress != null) { + if (mProgress instanceof SeekBar) { + SeekBar seeker = (SeekBar) mProgress; + seeker.setOnSeekBarChangeListener(mSeekListener); + } + mProgress.setMax(1000); + } + + mEndTime = (TextView) v.findViewById(R.id.totalTimeText); + mCurrentTime = (TextView) v.findViewById(R.id.currentTimeText); + 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 + */ + 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. + } + } + + /** + * 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()) { + msg = obtainMessage(SHOW_PROGRESS); + sendMessageDelayed(msg, 1000 - (pos % 1000)); + } + break; + } + } + }; + + private String stringForTime(int timeMs) { + int totalSeconds = timeMs / 1000; + + int seconds = totalSeconds % 60; + int minutes = (totalSeconds / 60) % 60; + int hours = totalSeconds / 3600; + + mFormatBuilder.setLength(0); + if (hours > 0) { + return mFormatter.format("%d:%02d:%02d", hours, minutes, seconds).toString(); + } else { + return mFormatter.format("%02d:%02d", minutes, seconds).toString(); + } + } + + private int setProgress() { + if (mPlayer == null || mDragging) { + return 0; + } + int position = mPlayer.getCurrentPosition(); + int duration = mPlayer.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(); + mProgress.setSecondaryProgress(percent * 10); + } + + if (mEndTime != null) + mEndTime.setText(stringForTime(duration)); + if (mCurrentTime != null) + mCurrentTime.setText(stringForTime(position)); + + 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) { + int keyCode = event.getKeyCode(); + final boolean uniqueDown = event.getRepeatCount() == 0 + && event.getAction() == KeyEvent.ACTION_DOWN; + if (keyCode == KeyEvent.KEYCODE_HEADSETHOOK + || keyCode == KeyEvent.KEYCODE_MEDIA_PLAY_PAUSE + || keyCode == KeyEvent.KEYCODE_SPACE) { + if (uniqueDown) { + doPauseResume(); + show(sDefaultTimeout); + if (mPauseButton != null) { + mPauseButton.requestFocus(); + } + } + return true; + } else if (keyCode == KeyEvent.KEYCODE_MEDIA_PLAY) { + if (uniqueDown && !mPlayer.isPlaying()) { + mPlayer.start(); + updatePausePlay(); + show(sDefaultTimeout); + } + return true; + } else if (keyCode == KeyEvent.KEYCODE_MEDIA_STOP + || keyCode == KeyEvent.KEYCODE_MEDIA_PAUSE) { + 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(); + } + return true; + } + + show(sDefaultTimeout); + return super.dispatchKeyEvent(event); + } + + private View.OnClickListener mPauseListener = new View.OnClickListener() { + public void onClick(View v) { + doPauseResume(); + show(sDefaultTimeout); + } + }; + + private void updatePausePlay() { + if (mRoot == null || mPauseButton == null) + return; + + if (mPlayer.isPlaying()) { + mPauseButton.setImageResource(android.R.drawable.ic_media_pause); + } else { + mPauseButton.setImageResource(android.R.drawable.ic_media_play); + } + } + + private void doPauseResume() { + if (mPlayer.isPlaying()) { + mPlayer.pause(); + } else { + mPlayer.start(); + } + 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) { + 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); + } + + @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()); + } + + private View.OnClickListener mRewListener = new View.OnClickListener() { + public void onClick(View v) { + int pos = mPlayer.getCurrentPosition(); + pos -= 5000; // milliseconds + mPlayer.seekTo(pos); + setProgress(); + + show(sDefaultTimeout); + } + }; + + private View.OnClickListener mFfwdListener = new View.OnClickListener() { + public void onClick(View v) { + int pos = mPlayer.getCurrentPosition(); + pos += 15000; // milliseconds + mPlayer.seekTo(pos); + setProgress(); + + show(sDefaultTimeout); + } + }; + + private void installPrevNextListeners() { + if (mNextButton != null) { + mNextButton.setOnClickListener(mNextListener); + mNextButton.setEnabled(mNextListener != null); + } + + if (mPrevButton != null) { + mPrevButton.setOnClickListener(mPrevListener); + mPrevButton.setEnabled(mPrevListener != null); + } + } + + public void setPrevNextListeners(View.OnClickListener next, View.OnClickListener prev) { + mNextListener = next; + mPrevListener = prev; + mListenersSet = true; + + if (mRoot != null) { + installPrevNextListeners(); + + if (mNextButton != null && !mFromXml) { + mNextButton.setVisibility(View.VISIBLE); + } + if (mPrevButton != null && !mFromXml) { + mPrevButton.setVisibility(View.VISIBLE); + } + } + } + +} diff --git a/src/com/owncloud/android/ui/preview/PreviewMediaFragment.java b/src/com/owncloud/android/ui/preview/PreviewMediaFragment.java index d427bfda..f9fd122e 100644 --- a/src/com/owncloud/android/ui/preview/PreviewMediaFragment.java +++ b/src/com/owncloud/android/ui/preview/PreviewMediaFragment.java @@ -57,6 +57,7 @@ import com.actionbarsherlock.view.MenuInflater; import com.actionbarsherlock.view.MenuItem; import com.owncloud.android.datamodel.FileDataStorageManager; import com.owncloud.android.datamodel.OCFile; +import com.owncloud.android.media.MediaControlView; import com.owncloud.android.media.MediaService; import com.owncloud.android.media.MediaServiceBinder; import com.owncloud.android.network.OwnCloudClientUtils; @@ -104,7 +105,8 @@ public class PreviewMediaFragment extends SherlockFragment implements private RemoteOperation mLastRemoteOperation; private MediaServiceBinder mMediaServiceBinder = null; - private MediaController mMediaController = null; + //private MediaController mMediaController = null; + private MediaControlView mMediaController = null; private MediaServiceConnection mMediaServiceConnection = null; private VideoHelper mVideoHelper; @@ -167,6 +169,8 @@ public class PreviewMediaFragment extends SherlockFragment implements mImagePreview.setOnTouchListener(this); mVideoPreview = (VideoView)mView.findViewById(R.id.video_preview); + mMediaController = (MediaControlView)mView.findViewById(R.id.media_controller); + //updateFileDetails(false); return mView; } @@ -329,10 +333,14 @@ public class PreviewMediaFragment extends SherlockFragment implements mVideoPreview.setVideoPath(mFile.getStoragePath()); // create and prepare control panel for the user - mMediaController = new MediaController(getActivity()); - mMediaController.setMediaPlayer(mVideoPreview); - mMediaController.setAnchorView(mVideoPreview); - mVideoPreview.setMediaController(mMediaController); + //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(); + } } @@ -349,7 +357,7 @@ public class PreviewMediaFragment extends SherlockFragment implements public void onPrepared(MediaPlayer vp) { mVideoPreview.seekTo(mSavedPlaybackPosition); mVideoPreview.start(); - mMediaController.show(MediaService.MEDIA_CONTROL_SHORT_LIFE); + //mMediaController.show(MediaService.MEDIA_CONTROL_SHORT_LIFE); } @@ -377,9 +385,11 @@ public class PreviewMediaFragment extends SherlockFragment implements public boolean onError(MediaPlayer mp, int what, int extra) { Log.e(TAG, "Error in video playback, what = " + what + ", extra = " + extra); + /* if (mMediaController != null) { mMediaController.hide(); } + */ if (mVideoPreview.getWindowToken() != null) { String message = MediaService.getMessageForMediaError(getActivity(), what, extra); @@ -404,34 +414,12 @@ public class PreviewMediaFragment extends SherlockFragment implements @Override public void onResume() { super.onResume(); - /* - mDownloadFinishReceiver = new DownloadFinishReceiver(); - IntentFilter filter = new IntentFilter( - FileDownloader.DOWNLOAD_FINISH_MESSAGE); - getActivity().registerReceiver(mDownloadFinishReceiver, filter); - - mUploadFinishReceiver = new UploadFinishReceiver(); - filter = new IntentFilter(FileUploader.UPLOAD_FINISH_MESSAGE); - getActivity().registerReceiver(mUploadFinishReceiver, filter); - */ - } @Override public void onPause() { super.onPause(); - /* - if (mVideoPreview.getVisibility() == View.VISIBLE) { - mSavedPlaybackPosition = mVideoPreview.getCurrentPosition(); - }*/ - /* - getActivity().unregisterReceiver(mDownloadFinishReceiver); - mDownloadFinishReceiver = null; - - getActivity().unregisterReceiver(mUploadFinishReceiver); - mUploadFinishReceiver = null; - */ } @@ -441,15 +429,17 @@ public class PreviewMediaFragment extends SherlockFragment implements if (mMediaServiceConnection != null) { Log.d(TAG, "Unbinding from MediaService ..."); if (mMediaServiceBinder != null && mMediaController != null) { - mMediaServiceBinder.unregisterMediaController(mMediaController); + //mMediaServiceBinder.unregisterMediaController(mMediaController); } getActivity().unbindService(mMediaServiceConnection); mMediaServiceConnection = null; mMediaServiceBinder = null; + /* if (mMediaController != null) { mMediaController.hide(); mMediaController = null; } + */ } } @@ -477,11 +467,13 @@ public class PreviewMediaFragment extends SherlockFragment implements private void toggleMediaController(int time) { + /* if (mMediaController.isShowing()) { mMediaController.hide(); } else { mMediaController.show(time); } + */ } @@ -495,7 +487,7 @@ public class PreviewMediaFragment extends SherlockFragment implements mMediaServiceBinder.start(); } if (!mMediaController.isShowing() && isVisible()) { - mMediaController.show(MediaService.MEDIA_CONTROL_PERMANENT); + //mMediaController.show(MediaService.MEDIA_CONTROL_PERMANENT); // TODO - fix strange bug; steps to trigger : // 1. remove the "isVisible()" control // 2. start the app and preview an audio file @@ -528,9 +520,11 @@ public class PreviewMediaFragment extends SherlockFragment implements Log.d(TAG, "Media service connected"); mMediaServiceBinder = (MediaServiceBinder) service; if (mMediaServiceBinder != null) { + /* if (mMediaController == null) { mMediaController = new MediaController(getSherlockActivity()); } + */ prepareMediaController(); playAudio(); // do not wait for the touch of nobody to play audio @@ -543,10 +537,14 @@ public class PreviewMediaFragment extends SherlockFragment implements } private void prepareMediaController() { - mMediaServiceBinder.registerMediaController(mMediaController); - mMediaController.setMediaPlayer(mMediaServiceBinder); - mMediaController.setAnchorView(getView()); - mMediaController.setEnabled(mMediaServiceBinder.isInPlaybackState()); + //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(); + } } @Override @@ -554,9 +552,11 @@ public class PreviewMediaFragment extends SherlockFragment implements if (component.equals(new ComponentName(getActivity(), MediaService.class))) { Log.e(TAG, "Media service suddenly disconnected"); if (mMediaController != null) { - mMediaController.hide(); + //mMediaController.hide(); mMediaController.setMediaPlayer(null); - mMediaController = null; + //mMediaController = null; + } else { + Toast.makeText(getActivity(), "No media controller to release when disconnected from media service", Toast.LENGTH_SHORT).show(); } mMediaServiceBinder = null; mMediaServiceConnection = null; @@ -711,29 +711,6 @@ public class PreviewMediaFragment extends SherlockFragment implements /** - * Interface to implement by any Activity that includes some instance of FileDetailFragment - * - * @author David A. Velasco - */ - public interface ContainerActivity extends TransferServiceGetter { - - /** - * Callback method invoked when the detail fragment wants to notice its container - * activity about a relevant state the file shown by the fragment. - * - * Added to notify to FileDisplayActivity about the need of refresh the files list. - * - * Currently called when: - * - a download is started; - * - a rename is completed; - * - a deletion is completed; - * - the 'inSync' flag is changed; - */ - public void onFileStateChanged(); - - } - - /** * Helper method to test if an {@link OCFile} can be passed to a {@link PreviewMediaFragment} to be previewed. * * @param file File to test if can be previewed. @@ -775,7 +752,7 @@ public class PreviewMediaFragment extends SherlockFragment implements private void stopPreview(boolean stopAudio) { if (mMediaController != null) { - mMediaController.hide(); + //mMediaController.hide(); } if (mFile.isAudio() && stopAudio) { mMediaServiceBinder.pause();