FileDocCategorySizeDatePackage
MediaController.javaAPI DocAndroid 1.5 API18890Wed May 06 22:41:56 BST 2009android.widget

MediaController

public class MediaController extends FrameLayout
A view containing controls for a MediaPlayer. Typically contains the buttons like "Play/Pause", "Rewind", "Fast Forward" and a progress slider. It takes care of synchronizing the controls with the state of the MediaPlayer.

The way to use this class is to instantiate it programatically. The MediaController will create a default set of controls and put them in a window floating above your application. Specifically, the controls will float above the view specified with setAnchorView(). The window will disappear if left idle for three seconds and reappear when the user touches the anchor view.

Functions like show() and hide() have no effect when MediaController is created in an xml layout. MediaController will hide and show the buttons according to these rules:

  • The "previous" and "next" buttons are hidden until setPrevNextListeners() has been called
  • The "previous" and "next" buttons are visible but disabled if setPrevNextListeners() was called with null listeners
  • The "rewind" and "fastforward" buttons are shown unless requested otherwise by using the MediaController(Context, boolean) constructor with the boolean set to false

Fields Summary
private MediaPlayerControl
mPlayer
private android.content.Context
mContext
private android.view.View
mAnchor
private android.view.View
mRoot
private android.view.WindowManager
mWindowManager
private android.view.Window
mWindow
private android.view.View
mDecor
private ProgressBar
mProgress
private TextView
mEndTime
private TextView
mCurrentTime
private boolean
mShowing
private boolean
mDragging
private static final int
sDefaultTimeout
private static final int
FADE_OUT
private static final int
SHOW_PROGRESS
private boolean
mUseFastForward
private boolean
mFromXml
private boolean
mListenersSet
private View.OnClickListener
mNextListener
private View.OnClickListener
mPrevListener
StringBuilder
mFormatBuilder
Formatter
mFormatter
private ImageButton
mPauseButton
private ImageButton
mFfwdButton
private ImageButton
mRewButton
private ImageButton
mNextButton
private ImageButton
mPrevButton
private OnTouchListener
mTouchListener
private android.os.Handler
mHandler
private View.OnClickListener
mPauseListener
private android.widget.SeekBar.OnSeekBarChangeListener
mSeekListener
private View.OnClickListener
mRewListener
private View.OnClickListener
mFfwdListener
Constructors Summary
public MediaController(android.content.Context context, android.util.AttributeSet attrs)


         
        super(context, attrs);
        mRoot = this;
        mContext = context;
        mUseFastForward = true;
        mFromXml = true;
    
public MediaController(android.content.Context context, boolean useFastForward)

        super(context);
        mContext = context;
        mUseFastForward = useFastForward;
        initFloatingWindow();
    
public MediaController(android.content.Context context)

        super(context);
        mContext = context;
        mUseFastForward = true;
        initFloatingWindow();
    
Methods Summary
public booleandispatchKeyEvent(android.view.KeyEvent event)

        int keyCode = event.getKeyCode();
        if (event.getRepeatCount() == 0 && event.isDown() && (
                keyCode ==  KeyEvent.KEYCODE_HEADSETHOOK ||
                keyCode ==  KeyEvent.KEYCODE_MEDIA_PLAY_PAUSE ||
                keyCode ==  KeyEvent.KEYCODE_SPACE)) {
            doPauseResume();
            show(sDefaultTimeout);
            return true;
        } else if (keyCode ==  KeyEvent.KEYCODE_MEDIA_STOP) {
            if (mPlayer.isPlaying()) {
                mPlayer.pause();
                updatePausePlay();
            }
            return true;
        } else if (keyCode == KeyEvent.KEYCODE_VOLUME_DOWN ||
                keyCode == KeyEvent.KEYCODE_VOLUME_UP) {
            // don't show the controls for volume adjustment
            return super.dispatchKeyEvent(event);
        } else if (keyCode == KeyEvent.KEYCODE_BACK || keyCode == KeyEvent.KEYCODE_MENU) {
            hide();

            return true;
        } else {
            show(sDefaultTimeout);
        }
        return super.dispatchKeyEvent(event);
    
private voiddoPauseResume()

        if (mPlayer.isPlaying()) {
            mPlayer.pause();
        } else {
            mPlayer.start();
        }
        updatePausePlay();
    
public voidhide()
Remove the controller from the screen.

        if (mAnchor == null)
            return;

        if (mShowing) {
            try {
                mHandler.removeMessages(SHOW_PROGRESS);
                mWindowManager.removeView(mDecor);
            } catch (IllegalArgumentException ex) {
                Log.w("MediaController", "already removed");
            }
            mShowing = false;
        }
    
private voidinitControllerView(android.view.View v)

        mPauseButton = (ImageButton) v.findViewById(com.android.internal.R.id.pause);
        if (mPauseButton != null) {
            mPauseButton.requestFocus();
            mPauseButton.setOnClickListener(mPauseListener);
        }

        mFfwdButton = (ImageButton) v.findViewById(com.android.internal.R.id.ffwd);
        if (mFfwdButton != null) {
            mFfwdButton.setOnClickListener(mFfwdListener);
            if (!mFromXml) {
                mFfwdButton.setVisibility(mUseFastForward ? View.VISIBLE : View.GONE);
            }
        }

        mRewButton = (ImageButton) v.findViewById(com.android.internal.R.id.rew);
        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(com.android.internal.R.id.next);
        if (mNextButton != null && !mFromXml && !mListenersSet) {
            mNextButton.setVisibility(View.GONE);
        }
        mPrevButton = (ImageButton) v.findViewById(com.android.internal.R.id.prev);
        if (mPrevButton != null && !mFromXml && !mListenersSet) {
            mPrevButton.setVisibility(View.GONE);
        }

        mProgress = (ProgressBar) v.findViewById(com.android.internal.R.id.mediacontroller_progress);
        if (mProgress != null) {
            if (mProgress instanceof SeekBar) {
                SeekBar seeker = (SeekBar) mProgress;
                seeker.setOnSeekBarChangeListener(mSeekListener);
            }
            mProgress.setMax(1000);
        }

        mEndTime = (TextView) v.findViewById(com.android.internal.R.id.time);
        mCurrentTime = (TextView) v.findViewById(com.android.internal.R.id.time_current);
        mFormatBuilder = new StringBuilder();
        mFormatter = new Formatter(mFormatBuilder, Locale.getDefault());

        installPrevNextListeners();
    
private voidinitFloatingWindow()

        mWindowManager = (WindowManager)mContext.getSystemService("window");
        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();
    
private voidinstallPrevNextListeners()


       
        if (mNextButton != null) {
            mNextButton.setOnClickListener(mNextListener);
            mNextButton.setEnabled(mNextListener != null);
        }

        if (mPrevButton != null) {
            mPrevButton.setOnClickListener(mPrevListener);
            mPrevButton.setEnabled(mPrevListener != null);
        }
    
public booleanisShowing()

        return mShowing;
    
protected android.view.ViewmakeControllerView()
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

        LayoutInflater inflate = (LayoutInflater) mContext.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
        mRoot = inflate.inflate(com.android.internal.R.layout.media_controller, null);

        initControllerView(mRoot);

        return mRoot;
    
public voidonFinishInflate()

        if (mRoot != null)
            initControllerView(mRoot);
    
public booleanonTouchEvent(android.view.MotionEvent event)

        show(sDefaultTimeout);
        return true;
    
public booleanonTrackballEvent(android.view.MotionEvent ev)

        show(sDefaultTimeout);
        return false;
    
public voidsetAnchorView(android.view.View view)
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.

        mAnchor = view;

        FrameLayout.LayoutParams frameParams = new FrameLayout.LayoutParams(
                ViewGroup.LayoutParams.FILL_PARENT,
                ViewGroup.LayoutParams.FILL_PARENT
        );

        removeAllViews();
        View v = makeControllerView();
        addView(v, frameParams);
    
public voidsetEnabled(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);
        }

        super.setEnabled(enabled);
    
public voidsetMediaPlayer(android.widget.MediaController$MediaPlayerControl player)

    
        
        mPlayer = player;
        updatePausePlay();
    
public voidsetPrevNextListeners(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);
            }
        }
    
private intsetProgress()

        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;
    
public voidshow()
Show the controller on screen. It will go away automatically after 3 seconds of inactivity.

        show(sDefaultTimeout);
    
public voidshow(int timeout)
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.


        if (!mShowing && mAnchor != null) {
            setProgress();

            int [] anchorpos = new int[2];
            mAnchor.getLocationOnScreen(anchorpos);

            WindowManager.LayoutParams p = new WindowManager.LayoutParams();
            p.gravity = Gravity.TOP;
            p.width = mAnchor.getWidth();
            p.height = LayoutParams.WRAP_CONTENT;
            p.x = 0;
            p.y = anchorpos[1] + mAnchor.getHeight() - p.height;
            p.format = PixelFormat.TRANSLUCENT;
            p.type = WindowManager.LayoutParams.TYPE_APPLICATION_PANEL;
            p.flags |= WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM;
            p.token = null;
            p.windowAnimations = 0; // android.R.style.DropDownAnimationDown;
            mWindowManager.addView(mDecor, p);
            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);
        }
    
private java.lang.StringstringForTime(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 voidupdatePausePlay()


       
        if (mRoot == null)
            return;

        ImageButton button = (ImageButton) mRoot.findViewById(com.android.internal.R.id.pause);
        if (button == null)
            return;

        if (mPlayer.isPlaying()) {
            button.setImageResource(com.android.internal.R.drawable.ic_media_pause);
        } else {
            button.setImageResource(com.android.internal.R.drawable.ic_media_play);
        }