Want more features on Pastebin? Sign Up, it's FREE!
Guest

VideoControllerView.java

By: a guest on Jan 14th, 2013  |  syntax: Java  |  size: 23.06 KB  |  views: 5,795  |  expires: Never
download  |  raw  |  embed  |  report abuse  |  print
Text below is selected. Please press Ctrl+C to copy to your clipboard. (⌘+C on Mac)
  1. /*
  2.  * Copyright (C) 2006 The Android Open Source Project
  3.  *
  4.  * Licensed under the Apache License, Version 2.0 (the "License");
  5.  * you may not use this file except in compliance with the License.
  6.  * You may obtain a copy of the License at
  7.  *
  8.  *      http://www.apache.org/licenses/LICENSE-2.0
  9.  *
  10.  * Unless required by applicable law or agreed to in writing, software
  11.  * distributed under the License is distributed on an "AS IS" BASIS,
  12.  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  13.  * See the License for the specific language governing permissions and
  14.  * limitations under the License.
  15.  */
  16.  
  17. package your.package.name;
  18.  
  19. import android.content.Context;
  20. import android.os.Handler;
  21. import android.os.Message;
  22. import android.util.AttributeSet;
  23. import android.util.Log;
  24. import android.view.Gravity;
  25. import android.view.KeyEvent;
  26. import android.view.LayoutInflater;
  27. import android.view.MotionEvent;
  28. import android.view.View;
  29. import android.view.ViewGroup;
  30. import android.view.accessibility.AccessibilityEvent;
  31. import android.view.accessibility.AccessibilityNodeInfo;
  32. import android.widget.FrameLayout;
  33. import android.widget.ImageButton;
  34. import android.widget.ProgressBar;
  35. import android.widget.SeekBar;
  36. import android.widget.SeekBar.OnSeekBarChangeListener;
  37. import android.widget.TextView;
  38.  
  39. import java.lang.ref.WeakReference;
  40. import java.util.Formatter;
  41. import java.util.Locale;
  42.  
  43. import your.resource.path;
  44.  
  45. /**
  46.  * A view containing controls for a MediaPlayer. Typically contains the
  47.  * buttons like "Play/Pause", "Rewind", "Fast Forward" and a progress
  48.  * slider. It takes care of synchronizing the controls with the state
  49.  * of the MediaPlayer.
  50.  * <p>
  51.  * The way to use this class is to instantiate it programatically.
  52.  * The MediaController will create a default set of controls
  53.  * and put them in a window floating above your application. Specifically,
  54.  * the controls will float above the view specified with setAnchorView().
  55.  * The window will disappear if left idle for three seconds and reappear
  56.  * when the user touches the anchor view.
  57.  * <p>
  58.  * Functions like show() and hide() have no effect when MediaController
  59.  * is created in an xml layout.
  60.  *
  61.  * MediaController will hide and
  62.  * show the buttons according to these rules:
  63.  * <ul>
  64.  * <li> The "previous" and "next" buttons are hidden until setPrevNextListeners()
  65.  *   has been called
  66.  * <li> The "previous" and "next" buttons are visible but disabled if
  67.  *   setPrevNextListeners() was called with null listeners
  68.  * <li> The "rewind" and "fastforward" buttons are shown unless requested
  69.  *   otherwise by using the MediaController(Context, boolean) constructor
  70.  *   with the boolean set to false
  71.  * </ul>
  72.  */
  73. public class VideoControllerView extends FrameLayout {
  74.     private static final String TAG = "VideoControllerView";
  75.    
  76.     private MediaPlayerControl  mPlayer;
  77.     private Context             mContext;
  78.     private ViewGroup           mAnchor;
  79.     private View                mRoot;
  80.     private ProgressBar         mProgress;
  81.     private TextView            mEndTime, mCurrentTime;
  82.     private boolean             mShowing;
  83.     private boolean             mDragging;
  84.     private static final int    sDefaultTimeout = 3000;
  85.     private static final int    FADE_OUT = 1;
  86.     private static final int    SHOW_PROGRESS = 2;
  87.     private boolean             mUseFastForward;
  88.     private boolean             mFromXml;
  89.     private boolean             mListenersSet;
  90.     private View.OnClickListener mNextListener, mPrevListener;
  91.     StringBuilder               mFormatBuilder;
  92.     Formatter                   mFormatter;
  93.     private ImageButton         mPauseButton;
  94.     private ImageButton         mFfwdButton;
  95.     private ImageButton         mRewButton;
  96.     private ImageButton         mNextButton;
  97.     private ImageButton         mPrevButton;
  98.     private ImageButton         mFullscreenButton;
  99.     private Handler             mHandler = new MessageHandler(this);
  100.  
  101.     public VideoControllerView(Context context, AttributeSet attrs) {
  102.         super(context, attrs);
  103.         mRoot = null;
  104.         mContext = context;
  105.         mUseFastForward = true;
  106.         mFromXml = true;
  107.        
  108.         Log.i(TAG, TAG);
  109.     }
  110.  
  111.     public VideoControllerView(Context context, boolean useFastForward) {
  112.         super(context);
  113.         mContext = context;
  114.         mUseFastForward = useFastForward;
  115.        
  116.         Log.i(TAG, TAG);
  117.     }
  118.  
  119.     public VideoControllerView(Context context) {
  120.         this(context, true);
  121.  
  122.         Log.i(TAG, TAG);
  123.     }
  124.  
  125.     @Override
  126.     public void onFinishInflate() {
  127.         if (mRoot != null)
  128.             initControllerView(mRoot);
  129.     }
  130.    
  131.     public void setMediaPlayer(MediaPlayerControl player) {
  132.         mPlayer = player;
  133.         updatePausePlay();
  134.         updateFullScreen();
  135.     }
  136.  
  137.     /**
  138.      * Set the view that acts as the anchor for the control view.
  139.      * This can for example be a VideoView, or your Activity's main view.
  140.      * @param view The view to which to anchor the controller when it is visible.
  141.      */
  142.     public void setAnchorView(ViewGroup view) {
  143.         mAnchor = view;
  144.  
  145.         FrameLayout.LayoutParams frameParams = new FrameLayout.LayoutParams(
  146.                 ViewGroup.LayoutParams.MATCH_PARENT,
  147.                 ViewGroup.LayoutParams.MATCH_PARENT
  148.         );
  149.  
  150.         removeAllViews();
  151.         View v = makeControllerView();
  152.         addView(v, frameParams);
  153.     }
  154.  
  155.     /**
  156.      * Create the view that holds the widgets that control playback.
  157.      * Derived classes can override this to create their own.
  158.      * @return The controller view.
  159.      * @hide This doesn't work as advertised
  160.      */
  161.     protected View makeControllerView() {
  162.         LayoutInflater inflate = (LayoutInflater) mContext.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
  163.         mRoot = inflate.inflate(R.layout.media_controller, null);
  164.  
  165.         initControllerView(mRoot);
  166.  
  167.         return mRoot;
  168.     }
  169.  
  170.     private void initControllerView(View v) {
  171.         mPauseButton = (ImageButton) v.findViewById(R.id.pause);
  172.         if (mPauseButton != null) {
  173.             mPauseButton.requestFocus();
  174.             mPauseButton.setOnClickListener(mPauseListener);
  175.         }
  176.        
  177.         mFullscreenButton = (ImageButton) v.findViewById(R.id.fullscreen);
  178.         if (mFullscreenButton != null) {
  179.             mFullscreenButton.requestFocus();
  180.             mFullscreenButton.setOnClickListener(mFullscreenListener);
  181.         }
  182.  
  183.         mFfwdButton = (ImageButton) v.findViewById(R.id.ffwd);
  184.         if (mFfwdButton != null) {
  185.             mFfwdButton.setOnClickListener(mFfwdListener);
  186.             if (!mFromXml) {
  187.                 mFfwdButton.setVisibility(mUseFastForward ? View.VISIBLE : View.GONE);
  188.             }
  189.         }
  190.  
  191.         mRewButton = (ImageButton) v.findViewById(R.id.rew);
  192.         if (mRewButton != null) {
  193.             mRewButton.setOnClickListener(mRewListener);
  194.             if (!mFromXml) {
  195.                 mRewButton.setVisibility(mUseFastForward ? View.VISIBLE : View.GONE);
  196.             }
  197.         }
  198.  
  199.         // By default these are hidden. They will be enabled when setPrevNextListeners() is called
  200.         mNextButton = (ImageButton) v.findViewById(R.id.next);
  201.         if (mNextButton != null && !mFromXml && !mListenersSet) {
  202.             mNextButton.setVisibility(View.GONE);
  203.         }
  204.         mPrevButton = (ImageButton) v.findViewById(R.id.prev);
  205.         if (mPrevButton != null && !mFromXml && !mListenersSet) {
  206.             mPrevButton.setVisibility(View.GONE);
  207.         }
  208.  
  209.         mProgress = (ProgressBar) v.findViewById(R.id.mediacontroller_progress);
  210.         if (mProgress != null) {
  211.             if (mProgress instanceof SeekBar) {
  212.                 SeekBar seeker = (SeekBar) mProgress;
  213.                 seeker.setOnSeekBarChangeListener(mSeekListener);
  214.             }
  215.             mProgress.setMax(1000);
  216.         }
  217.  
  218.         mEndTime = (TextView) v.findViewById(R.id.time);
  219.         mCurrentTime = (TextView) v.findViewById(R.id.time_current);
  220.         mFormatBuilder = new StringBuilder();
  221.         mFormatter = new Formatter(mFormatBuilder, Locale.getDefault());
  222.  
  223.         installPrevNextListeners();
  224.     }
  225.  
  226.     /**
  227.      * Show the controller on screen. It will go away
  228.      * automatically after 3 seconds of inactivity.
  229.      */
  230.     public void show() {
  231.         show(sDefaultTimeout);
  232.     }
  233.  
  234.     /**
  235.      * Disable pause or seek buttons if the stream cannot be paused or seeked.
  236.      * This requires the control interface to be a MediaPlayerControlExt
  237.      */
  238.     private void disableUnsupportedButtons() {
  239.         if (mPlayer == null) {
  240.             return;
  241.         }
  242.        
  243.         try {
  244.             if (mPauseButton != null && !mPlayer.canPause()) {
  245.                 mPauseButton.setEnabled(false);
  246.             }
  247.             if (mRewButton != null && !mPlayer.canSeekBackward()) {
  248.                 mRewButton.setEnabled(false);
  249.             }
  250.             if (mFfwdButton != null && !mPlayer.canSeekForward()) {
  251.                 mFfwdButton.setEnabled(false);
  252.             }
  253.         } catch (IncompatibleClassChangeError ex) {
  254.             // We were given an old version of the interface, that doesn't have
  255.             // the canPause/canSeekXYZ methods. This is OK, it just means we
  256.             // assume the media can be paused and seeked, and so we don't disable
  257.             // the buttons.
  258.         }
  259.     }
  260.    
  261.     /**
  262.      * Show the controller on screen. It will go away
  263.      * automatically after 'timeout' milliseconds of inactivity.
  264.      * @param timeout The timeout in milliseconds. Use 0 to show
  265.      * the controller until hide() is called.
  266.      */
  267.     public void show(int timeout) {
  268.         if (!mShowing && mAnchor != null) {
  269.             setProgress();
  270.             if (mPauseButton != null) {
  271.                 mPauseButton.requestFocus();
  272.             }
  273.             disableUnsupportedButtons();
  274.  
  275.             FrameLayout.LayoutParams tlp = new FrameLayout.LayoutParams(
  276.                 ViewGroup.LayoutParams.MATCH_PARENT,
  277.                 ViewGroup.LayoutParams.WRAP_CONTENT,
  278.                 Gravity.BOTTOM
  279.             );
  280.            
  281.             mAnchor.addView(this, tlp);
  282.             mShowing = true;
  283.         }
  284.         updatePausePlay();
  285.         updateFullScreen();
  286.        
  287.         // cause the progress bar to be updated even if mShowing
  288.         // was already true.  This happens, for example, if we're
  289.         // paused with the progress bar showing the user hits play.
  290.         mHandler.sendEmptyMessage(SHOW_PROGRESS);
  291.  
  292.         Message msg = mHandler.obtainMessage(FADE_OUT);
  293.         if (timeout != 0) {
  294.             mHandler.removeMessages(FADE_OUT);
  295.             mHandler.sendMessageDelayed(msg, timeout);
  296.         }
  297.     }
  298.    
  299.     public boolean isShowing() {
  300.         return mShowing;
  301.     }
  302.  
  303.     /**
  304.      * Remove the controller from the screen.
  305.      */
  306.     public void hide() {
  307.         if (mAnchor == null) {
  308.             return;
  309.         }
  310.  
  311.         try {
  312.             mAnchor.removeView(this);
  313.             mHandler.removeMessages(SHOW_PROGRESS);
  314.         } catch (IllegalArgumentException ex) {
  315.             Log.w("MediaController", "already removed");
  316.         }
  317.         mShowing = false;
  318.     }
  319.  
  320.     private String stringForTime(int timeMs) {
  321.         int totalSeconds = timeMs / 1000;
  322.  
  323.         int seconds = totalSeconds % 60;
  324.         int minutes = (totalSeconds / 60) % 60;
  325.         int hours   = totalSeconds / 3600;
  326.  
  327.         mFormatBuilder.setLength(0);
  328.         if (hours > 0) {
  329.             return mFormatter.format("%d:%02d:%02d", hours, minutes, seconds).toString();
  330.         } else {
  331.             return mFormatter.format("%02d:%02d", minutes, seconds).toString();
  332.         }
  333.     }
  334.  
  335.     private int setProgress() {
  336.         if (mPlayer == null || mDragging) {
  337.             return 0;
  338.         }
  339.        
  340.         int position = mPlayer.getCurrentPosition();
  341.         int duration = mPlayer.getDuration();
  342.         if (mProgress != null) {
  343.             if (duration > 0) {
  344.                 // use long to avoid overflow
  345.                 long pos = 1000L * position / duration;
  346.                 mProgress.setProgress( (int) pos);
  347.             }
  348.             int percent = mPlayer.getBufferPercentage();
  349.             mProgress.setSecondaryProgress(percent * 10);
  350.         }
  351.  
  352.         if (mEndTime != null)
  353.             mEndTime.setText(stringForTime(duration));
  354.         if (mCurrentTime != null)
  355.             mCurrentTime.setText(stringForTime(position));
  356.  
  357.         return position;
  358.     }
  359.  
  360.     @Override
  361.     public boolean onTouchEvent(MotionEvent event) {
  362.         show(sDefaultTimeout);
  363.         return true;
  364.     }
  365.  
  366.     @Override
  367.     public boolean onTrackballEvent(MotionEvent ev) {
  368.         show(sDefaultTimeout);
  369.         return false;
  370.     }
  371.  
  372.     @Override
  373.     public boolean dispatchKeyEvent(KeyEvent event) {
  374.         if (mPlayer == null) {
  375.             return true;
  376.         }
  377.        
  378.         int keyCode = event.getKeyCode();
  379.         final boolean uniqueDown = event.getRepeatCount() == 0
  380.                 && event.getAction() == KeyEvent.ACTION_DOWN;
  381.         if (keyCode ==  KeyEvent.KEYCODE_HEADSETHOOK
  382.                 || keyCode == KeyEvent.KEYCODE_MEDIA_PLAY_PAUSE
  383.                 || keyCode == KeyEvent.KEYCODE_SPACE) {
  384.             if (uniqueDown) {
  385.                 doPauseResume();
  386.                 show(sDefaultTimeout);
  387.                 if (mPauseButton != null) {
  388.                     mPauseButton.requestFocus();
  389.                 }
  390.             }
  391.             return true;
  392.         } else if (keyCode == KeyEvent.KEYCODE_MEDIA_PLAY) {
  393.             if (uniqueDown && !mPlayer.isPlaying()) {
  394.                 mPlayer.start();
  395.                 updatePausePlay();
  396.                 show(sDefaultTimeout);
  397.             }
  398.             return true;
  399.         } else if (keyCode == KeyEvent.KEYCODE_MEDIA_STOP
  400.                 || keyCode == KeyEvent.KEYCODE_MEDIA_PAUSE) {
  401.             if (uniqueDown && mPlayer.isPlaying()) {
  402.                 mPlayer.pause();
  403.                 updatePausePlay();
  404.                 show(sDefaultTimeout);
  405.             }
  406.             return true;
  407.         } else if (keyCode == KeyEvent.KEYCODE_VOLUME_DOWN
  408.                 || keyCode == KeyEvent.KEYCODE_VOLUME_UP
  409.                 || keyCode == KeyEvent.KEYCODE_VOLUME_MUTE) {
  410.             // don't show the controls for volume adjustment
  411.             return super.dispatchKeyEvent(event);
  412.         } else if (keyCode == KeyEvent.KEYCODE_BACK || keyCode == KeyEvent.KEYCODE_MENU) {
  413.             if (uniqueDown) {
  414.                 hide();
  415.             }
  416.             return true;
  417.         }
  418.  
  419.         show(sDefaultTimeout);
  420.         return super.dispatchKeyEvent(event);
  421.     }
  422.  
  423.     private View.OnClickListener mPauseListener = new View.OnClickListener() {
  424.         public void onClick(View v) {
  425.             doPauseResume();
  426.             show(sDefaultTimeout);
  427.         }
  428.     };
  429.  
  430.     private View.OnClickListener mFullscreenListener = new View.OnClickListener() {
  431.         public void onClick(View v) {
  432.             doToggleFullscreen();
  433.             show(sDefaultTimeout);
  434.         }
  435.     };
  436.  
  437.     public void updatePausePlay() {
  438.         if (mRoot == null || mPauseButton == null || mPlayer == null) {
  439.             return;
  440.         }
  441.  
  442.         if (mPlayer.isPlaying()) {
  443.             mPauseButton.setImageResource(R.drawable.ic_media_pause);
  444.         } else {
  445.             mPauseButton.setImageResource(R.drawable.ic_media_play);
  446.         }
  447.     }
  448.  
  449.     public void updateFullScreen() {
  450.         if (mRoot == null || mFullscreenButton == null || mPlayer == null) {
  451.             return;
  452.         }
  453.        
  454.         if (mPlayer.isFullScreen()) {
  455.             mFullscreenButton.setImageResource(R.drawable.ic_media_fullscreen_shrink);
  456.         }
  457.         else {
  458.             mFullscreenButton.setImageResource(R.drawable.ic_media_fullscreen_stretch);
  459.         }
  460.     }
  461.  
  462.     private void doPauseResume() {
  463.         if (mPlayer == null) {
  464.             return;
  465.         }
  466.        
  467.         if (mPlayer.isPlaying()) {
  468.             mPlayer.pause();
  469.         } else {
  470.             mPlayer.start();
  471.         }
  472.         updatePausePlay();
  473.     }
  474.  
  475.     private void doToggleFullscreen() {
  476.         if (mPlayer == null) {
  477.             return;
  478.         }
  479.        
  480.         mPlayer.toggleFullScreen();
  481.     }
  482.  
  483.     // There are two scenarios that can trigger the seekbar listener to trigger:
  484.     //
  485.     // The first is the user using the touchpad to adjust the posititon of the
  486.     // seekbar's thumb. In this case onStartTrackingTouch is called followed by
  487.     // a number of onProgressChanged notifications, concluded by onStopTrackingTouch.
  488.     // We're setting the field "mDragging" to true for the duration of the dragging
  489.     // session to avoid jumps in the position in case of ongoing playback.
  490.     //
  491.     // The second scenario involves the user operating the scroll ball, in this
  492.     // case there WON'T BE onStartTrackingTouch/onStopTrackingTouch notifications,
  493.     // we will simply apply the updated position without suspending regular updates.
  494.     private OnSeekBarChangeListener mSeekListener = new OnSeekBarChangeListener() {
  495.         public void onStartTrackingTouch(SeekBar bar) {
  496.             show(3600000);
  497.  
  498.             mDragging = true;
  499.  
  500.             // By removing these pending progress messages we make sure
  501.             // that a) we won't update the progress while the user adjusts
  502.             // the seekbar and b) once the user is done dragging the thumb
  503.             // we will post one of these messages to the queue again and
  504.             // this ensures that there will be exactly one message queued up.
  505.             mHandler.removeMessages(SHOW_PROGRESS);
  506.         }
  507.  
  508.         public void onProgressChanged(SeekBar bar, int progress, boolean fromuser) {
  509.             if (mPlayer == null) {
  510.                 return;
  511.             }
  512.            
  513.             if (!fromuser) {
  514.                 // We're not interested in programmatically generated changes to
  515.                 // the progress bar's position.
  516.                 return;
  517.             }
  518.  
  519.             long duration = mPlayer.getDuration();
  520.             long newposition = (duration * progress) / 1000L;
  521.             mPlayer.seekTo( (int) newposition);
  522.             if (mCurrentTime != null)
  523.                 mCurrentTime.setText(stringForTime( (int) newposition));
  524.         }
  525.  
  526.         public void onStopTrackingTouch(SeekBar bar) {
  527.             mDragging = false;
  528.             setProgress();
  529.             updatePausePlay();
  530.             show(sDefaultTimeout);
  531.  
  532.             // Ensure that progress is properly updated in the future,
  533.             // the call to show() does not guarantee this because it is a
  534.             // no-op if we are already showing.
  535.             mHandler.sendEmptyMessage(SHOW_PROGRESS);
  536.         }
  537.     };
  538.  
  539.     @Override
  540.     public void setEnabled(boolean enabled) {
  541.         if (mPauseButton != null) {
  542.             mPauseButton.setEnabled(enabled);
  543.         }
  544.         if (mFfwdButton != null) {
  545.             mFfwdButton.setEnabled(enabled);
  546.         }
  547.         if (mRewButton != null) {
  548.             mRewButton.setEnabled(enabled);
  549.         }
  550.         if (mNextButton != null) {
  551.             mNextButton.setEnabled(enabled && mNextListener != null);
  552.         }
  553.         if (mPrevButton != null) {
  554.             mPrevButton.setEnabled(enabled && mPrevListener != null);
  555.         }
  556.         if (mProgress != null) {
  557.             mProgress.setEnabled(enabled);
  558.         }
  559.         disableUnsupportedButtons();
  560.         super.setEnabled(enabled);
  561.     }
  562.  
  563.     @Override
  564.     public void onInitializeAccessibilityEvent(AccessibilityEvent event) {
  565.         super.onInitializeAccessibilityEvent(event);
  566.         event.setClassName(VideoControllerView.class.getName());
  567.     }
  568.  
  569.     @Override
  570.     public void onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo info) {
  571.         super.onInitializeAccessibilityNodeInfo(info);
  572.         info.setClassName(VideoControllerView.class.getName());
  573.     }
  574.  
  575.     private View.OnClickListener mRewListener = new View.OnClickListener() {
  576.         public void onClick(View v) {
  577.             if (mPlayer == null) {
  578.                 return;
  579.             }
  580.            
  581.             int pos = mPlayer.getCurrentPosition();
  582.             pos -= 5000; // milliseconds
  583.             mPlayer.seekTo(pos);
  584.             setProgress();
  585.  
  586.             show(sDefaultTimeout);
  587.         }
  588.     };
  589.  
  590.     private View.OnClickListener mFfwdListener = new View.OnClickListener() {
  591.         public void onClick(View v) {
  592.             if (mPlayer == null) {
  593.                 return;
  594.             }
  595.            
  596.             int pos = mPlayer.getCurrentPosition();
  597.             pos += 15000; // milliseconds
  598.             mPlayer.seekTo(pos);
  599.             setProgress();
  600.  
  601.             show(sDefaultTimeout);
  602.         }
  603.     };
  604.  
  605.     private void installPrevNextListeners() {
  606.         if (mNextButton != null) {
  607.             mNextButton.setOnClickListener(mNextListener);
  608.             mNextButton.setEnabled(mNextListener != null);
  609.         }
  610.  
  611.         if (mPrevButton != null) {
  612.             mPrevButton.setOnClickListener(mPrevListener);
  613.             mPrevButton.setEnabled(mPrevListener != null);
  614.         }
  615.     }
  616.  
  617.     public void setPrevNextListeners(View.OnClickListener next, View.OnClickListener prev) {
  618.         mNextListener = next;
  619.         mPrevListener = prev;
  620.         mListenersSet = true;
  621.  
  622.         if (mRoot != null) {
  623.             installPrevNextListeners();
  624.            
  625.             if (mNextButton != null && !mFromXml) {
  626.                 mNextButton.setVisibility(View.VISIBLE);
  627.             }
  628.             if (mPrevButton != null && !mFromXml) {
  629.                 mPrevButton.setVisibility(View.VISIBLE);
  630.             }
  631.         }
  632.     }
  633.    
  634.     public interface MediaPlayerControl {
  635.         void    start();
  636.         void    pause();
  637.         int     getDuration();
  638.         int     getCurrentPosition();
  639.         void    seekTo(int pos);
  640.         boolean isPlaying();
  641.         int     getBufferPercentage();
  642.         boolean canPause();
  643.         boolean canSeekBackward();
  644.         boolean canSeekForward();
  645.         boolean isFullScreen();
  646.         void    toggleFullScreen();
  647.     }
  648.    
  649.     private static class MessageHandler extends Handler {
  650.         private final WeakReference<VideoControllerView> mView;
  651.  
  652.         MessageHandler(VideoControllerView view) {
  653.             mView = new WeakReference<VideoControllerView>(view);
  654.         }
  655.         @Override
  656.         public void handleMessage(Message msg) {
  657.             VideoControllerView view = mView.get();
  658.             if (view == null || view.mPlayer == null) {
  659.                 return;
  660.             }
  661.            
  662.             int pos;
  663.             switch (msg.what) {
  664.                 case FADE_OUT:
  665.                     view.hide();
  666.                     break;
  667.                 case SHOW_PROGRESS:
  668.                     pos = view.setProgress();
  669.                     if (!view.mDragging && view.mShowing && view.mPlayer.isPlaying()) {
  670.                         msg = obtainMessage(SHOW_PROGRESS);
  671.                         sendMessageDelayed(msg, 1000 - (pos % 1000));
  672.                     }
  673.                     break;
  674.             }
  675.         }
  676.     }
  677. }
clone this paste RAW Paste Data