2011-10-03 128 views
10

我想用android.widget.VideoView流內容。 我需要確保在使用setVideoURI(Uri)時,VideoView將包含來自之前HttpClient調用的Cookie。 我在源代碼中看到有setVideoUri(Uri,Headers),但它有一個@hide JavaDoc註釋,並且不會編譯。VideoView與餅乾(或標題)

那麼,無論如何,要通過cookie或HTTP請求通過VideoView的標頭?

謝謝。

+0

#marc2112請查看我的回答 – Siavash

回答

8

提取物類VideoView從SDK。 然後,您可以在您自己的VideoView類上撥打setVideoURI(Uri uri, Map<String, String> headers)。元數據是不是因爲mp.getMetadata(MediaPlayer.METADATA_ALL, MediaPlayer.BYPASS_METADATA_FILTER)提取

注意是無法訪問的,但你可以用MediaMetadataRetriever

VideoView

import java.io.IOException; 
import java.util.Map; 

import android.app.AlertDialog; 
import android.content.Context; 
import android.content.DialogInterface; 
import android.content.Intent; 
import android.content.res.Resources; 
import android.media.AudioManager; 
import android.media.MediaPlayer; 
import android.media.MediaPlayer.OnCompletionListener; 
import android.media.MediaPlayer.OnErrorListener; 
import android.net.Uri; 
import android.util.AttributeSet; 
import android.util.Log; 
import android.view.KeyEvent; 
import android.view.MotionEvent; 
import android.view.SurfaceHolder; 
import android.view.SurfaceView; 
import android.view.View; 
import android.view.accessibility.AccessibilityEvent; 
import android.view.accessibility.AccessibilityNodeInfo; 
import android.widget.MediaController; 
import android.widget.MediaController.MediaPlayerControl; 


/** 
* Displays a video file. The VideoView class can load images from various sources (such as resources or content 
* providers), takes care of computing its measurement from the video so that it can be used in any layout manager, and 
* provides various display options such as scaling and tinting. 
*/ 
public class VideoView extends SurfaceView implements MediaPlayerControl { 

    private String TAG = "VideoView"; 

    // settable by the client 
    private Uri mUri; 

    private Map<String, String> mHeaders; 

    private int mDuration; 

    // all possible internal states 
    private static final int STATE_ERROR = - 1; 

    private static final int STATE_IDLE = 0; 

    private static final int STATE_PREPARING = 1; 

    private static final int STATE_PREPARED = 2; 

    private static final int STATE_PLAYING = 3; 

    private static final int STATE_PAUSED = 4; 

    private static final int STATE_PLAYBACK_COMPLETED = 5; 

    // mCurrentState is a VideoView object's current state. 
    // mTargetState is the state that a method caller intends to reach. 
    // For instance, regardless the VideoView object's current state, 
    // calling pause() intends to bring the object to a target state 
    // of STATE_PAUSED. 
    private int mCurrentState = STATE_IDLE; 

    private int mTargetState = STATE_IDLE; 

    // All the stuff we need for playing and showing a video 
    private SurfaceHolder mSurfaceHolder = null; 

    private MediaPlayer mMediaPlayer = null; 

    private int mVideoWidth; 

    private int mVideoHeight; 

    private int mSurfaceWidth; 

    private int mSurfaceHeight; 

    private MediaController mMediaController; 

    private OnCompletionListener mOnCompletionListener; 

    private MediaPlayer.OnPreparedListener mOnPreparedListener; 

    private int mCurrentBufferPercentage; 

    private OnErrorListener mOnErrorListener; 

    private int mSeekWhenPrepared; // recording the seek position while preparing 

    private boolean mCanPause; 

    private boolean mCanSeekBack; 

    private boolean mCanSeekForward; 

    public VideoView(Context context) { 
     super(context); 
     initVideoView(); 
    } 

    public VideoView(Context context, AttributeSet attrs) { 
     this(context, attrs, 0); 
     initVideoView(); 
    } 

    public VideoView(Context context, AttributeSet attrs, int defStyle) { 
     super(context, attrs, defStyle); 
     initVideoView(); 
    } 

    @Override 
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { 
     // Log.i("@@@@", "onMeasure"); 
     int width = getDefaultSize(mVideoWidth, widthMeasureSpec); 
     int height = getDefaultSize(mVideoHeight, heightMeasureSpec); 
     if(mVideoWidth > 0 && mVideoHeight > 0) { 
      if(mVideoWidth * height > width * mVideoHeight) { 
       // Log.i("@@@", "image too tall, correcting"); 
       height = width * mVideoHeight/mVideoWidth; 
      } else if(mVideoWidth * height < width * mVideoHeight) { 
       // Log.i("@@@", "image too wide, correcting"); 
       width = height * mVideoWidth/mVideoHeight; 
      } else { 
       // Log.i("@@@", "aspect ratio is correct: " + 
       // width+"/"+height+"="+ 
       // mVideoWidth+"/"+mVideoHeight); 
      } 
     } 
     // Log.i("@@@@@@@@@@", "setting size: " + width + 'x' + height); 
     setMeasuredDimension(width, height); 
    } 

    @Override 
    public void onInitializeAccessibilityEvent(AccessibilityEvent event) { 
     super.onInitializeAccessibilityEvent(event); 
     event.setClassName(VideoView.class.getName()); 
    } 

    @Override 
    public void onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo info) { 
     super.onInitializeAccessibilityNodeInfo(info); 
     info.setClassName(VideoView.class.getName()); 
    } 

    public int resolveAdjustedSize(int desiredSize, int measureSpec) { 
     int result = desiredSize; 
     int specMode = MeasureSpec.getMode(measureSpec); 
     int specSize = MeasureSpec.getSize(measureSpec); 

     switch(specMode) { 
      case MeasureSpec.UNSPECIFIED: 
       /* 
       * Parent says we can be as big as we want. Just don't be larger than max size imposed on ourselves. 
       */ 
       result = desiredSize; 
       break; 

      case MeasureSpec.AT_MOST: 
       /* 
       * Parent says we can be as big as we want, up to specSize. Don't be larger than specSize, and don't be 
       * larger than the max size imposed on ourselves. 
       */ 
       result = Math.min(desiredSize, specSize); 
       break; 

      case MeasureSpec.EXACTLY: 
       // No choice. Do what we are told. 
       result = specSize; 
       break; 
     } 
     return result; 
    } 

    private void initVideoView() { 
     mVideoWidth = 0; 
     mVideoHeight = 0; 
     getHolder().addCallback(mSHCallback); 
     getHolder().setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS); 
     setFocusable(true); 
     setFocusableInTouchMode(true); 
     requestFocus(); 
     mCurrentState = STATE_IDLE; 
     mTargetState = STATE_IDLE; 
    } 

    public void setVideoPath(String path) { 
     setVideoURI(Uri.parse(path)); 
    } 

    public void setVideoURI(Uri uri) { 
     setVideoURI(uri, null); 
    } 

    /** 
    * @hide 
    */ 
    public void setVideoURI(Uri uri, Map<String, String> headers) { 
     mUri = uri; 
     mHeaders = headers; 
     mSeekWhenPrepared = 0; 
     openVideo(); 
     requestLayout(); 
     invalidate(); 
    } 

    public void stopPlayback() { 
     if(mMediaPlayer != null) { 
      mMediaPlayer.stop(); 
      mMediaPlayer.release(); 
      mMediaPlayer = null; 
      mCurrentState = STATE_IDLE; 
      mTargetState = STATE_IDLE; 
     } 
    } 

    private void openVideo() { 
     if(mUri == null || mSurfaceHolder == null) { 
      // not ready for playback just yet, will try again later 
      return; 
     } 
     // Tell the music playback service to pause 
     // TODO: these constants need to be published somewhere in the framework. 
     Intent i = new Intent("com.android.music.musicservicecommand"); 
     i.putExtra("command", "pause"); 
     getContext().sendBroadcast(i); 

     // we shouldn't clear the target state, because somebody might have 
     // called start() previously 
     release(false); 
     try { 
      mMediaPlayer = new MediaPlayer(); 
      mMediaPlayer.setOnPreparedListener(mPreparedListener); 
      mMediaPlayer.setOnVideoSizeChangedListener(mSizeChangedListener); 
      mDuration = - 1; 
      mMediaPlayer.setOnCompletionListener(mCompletionListener); 
      mMediaPlayer.setOnErrorListener(mErrorListener); 
      mMediaPlayer.setOnBufferingUpdateListener(mBufferingUpdateListener); 
      mCurrentBufferPercentage = 0; 
      mMediaPlayer.setDataSource(getContext(), mUri, mHeaders); 
      mMediaPlayer.setDisplay(mSurfaceHolder); 
      mMediaPlayer.setAudioStreamType(AudioManager.STREAM_MUSIC); 
      mMediaPlayer.setScreenOnWhilePlaying(true); 
      mMediaPlayer.prepareAsync(); 
      // we don't set the target state here either, but preserve the 
      // target state that was there before. 
      mCurrentState = STATE_PREPARING; 
      attachMediaController(); 
     } catch(IOException ex) { 
      Log.w(TAG, "Unable to open content: " + mUri, ex); 
      mCurrentState = STATE_ERROR; 
      mTargetState = STATE_ERROR; 
      mErrorListener.onError(mMediaPlayer, MediaPlayer.MEDIA_ERROR_UNKNOWN, 0); 
      return; 
     } catch(IllegalArgumentException ex) { 
      Log.w(TAG, "Unable to open content: " + mUri, ex); 
      mCurrentState = STATE_ERROR; 
      mTargetState = STATE_ERROR; 
      mErrorListener.onError(mMediaPlayer, MediaPlayer.MEDIA_ERROR_UNKNOWN, 0); 
      return; 
     } 
    } 

    public void setMediaController(MediaController controller) { 
     if(mMediaController != null) { 
      mMediaController.hide(); 
     } 
     mMediaController = controller; 
     attachMediaController(); 
    } 

    private void attachMediaController() { 
     if(mMediaPlayer != null && mMediaController != null) { 
      mMediaController.setMediaPlayer(this); 
      View anchorView = this.getParent() instanceof View ? (View)this.getParent() : this; 
      mMediaController.setAnchorView(anchorView); 
      mMediaController.setEnabled(isInPlaybackState()); 
     } 
    } 

    MediaPlayer.OnVideoSizeChangedListener mSizeChangedListener = new MediaPlayer.OnVideoSizeChangedListener() { 

     public void onVideoSizeChanged(MediaPlayer mp, int width, int height) { 
      mVideoWidth = mp.getVideoWidth(); 
      mVideoHeight = mp.getVideoHeight(); 
      if(mVideoWidth != 0 && mVideoHeight != 0) { 
       getHolder().setFixedSize(mVideoWidth, mVideoHeight); 
      } 
     } 
    }; 

    MediaPlayer.OnPreparedListener mPreparedListener = new MediaPlayer.OnPreparedListener() { 

     public void onPrepared(MediaPlayer mp) { 
      mCurrentState = STATE_PREPARED; 

      // Get the capabilities of the player for this stream 

      // -_- where is the method ? 
      // Metadata data = mp.getMetadata(MediaPlayer.METADATA_ALL, MediaPlayer.BYPASS_METADATA_FILTER); 

      // use MediaMetadataRetriever to retrieve metadata 
      Metadata data = null; 

      if(data != null) { 
       mCanPause = ! data.has(Metadata.PAUSE_AVAILABLE) || data.getBoolean(Metadata.PAUSE_AVAILABLE); 
       mCanSeekBack = ! data.has(Metadata.SEEK_BACKWARD_AVAILABLE) || data.getBoolean(Metadata.SEEK_BACKWARD_AVAILABLE); 
       mCanSeekForward = ! data.has(Metadata.SEEK_FORWARD_AVAILABLE) || data.getBoolean(Metadata.SEEK_FORWARD_AVAILABLE); 
      } else { 
       mCanPause = mCanSeekBack = mCanSeekForward = true; 
      } 

      if(mOnPreparedListener != null) { 
       mOnPreparedListener.onPrepared(mMediaPlayer); 
      } 
      if(mMediaController != null) { 
       mMediaController.setEnabled(true); 
      } 
      mVideoWidth = mp.getVideoWidth(); 
      mVideoHeight = mp.getVideoHeight(); 

      int seekToPosition = mSeekWhenPrepared; // mSeekWhenPrepared may be changed after seekTo() call 
      if(seekToPosition != 0) { 
       seekTo(seekToPosition); 
      } 
      if(mVideoWidth != 0 && mVideoHeight != 0) { 
       // Log.i("@@@@", "video size: " + mVideoWidth +"/"+ mVideoHeight); 
       getHolder().setFixedSize(mVideoWidth, mVideoHeight); 
       if(mSurfaceWidth == mVideoWidth && mSurfaceHeight == mVideoHeight) { 
        // We didn't actually change the size (it was already at the size 
        // we need), so we won't get a "surface changed" callback, so 
        // start the video here instead of in the callback. 
        if(mTargetState == STATE_PLAYING) { 
         start(); 
         if(mMediaController != null) { 
          mMediaController.show(); 
         } 
        } else if(! isPlaying() && (seekToPosition != 0 || getCurrentPosition() > 0)) { 
         if(mMediaController != null) { 
          // Show the media controls when we're paused into a video and make 'em stick. 
          mMediaController.show(0); 
         } 
        } 
       } 
      } else { 
       // We don't know the video size yet, but should start anyway. 
       // The video size might be reported to us later. 
       if(mTargetState == STATE_PLAYING) { 
        start(); 
       } 
      } 
     } 
    }; 

    private MediaPlayer.OnCompletionListener mCompletionListener = new MediaPlayer.OnCompletionListener() { 

     public void onCompletion(MediaPlayer mp) { 
      mCurrentState = STATE_PLAYBACK_COMPLETED; 
      mTargetState = STATE_PLAYBACK_COMPLETED; 
      if(mMediaController != null) { 
       mMediaController.hide(); 
      } 
      if(mOnCompletionListener != null) { 
       mOnCompletionListener.onCompletion(mMediaPlayer); 
      } 
     } 
    }; 

    private MediaPlayer.OnErrorListener mErrorListener = new MediaPlayer.OnErrorListener() { 

     public boolean onError(MediaPlayer mp, int framework_err, int impl_err) { 
      Log.d(TAG, "Error: " + framework_err + "," + impl_err); 
      mCurrentState = STATE_ERROR; 
      mTargetState = STATE_ERROR; 
      if(mMediaController != null) { 
       mMediaController.hide(); 
      } 

      /* If an error handler has been supplied, use it and finish. */ 
      if(mOnErrorListener != null) { 
       if(mOnErrorListener.onError(mMediaPlayer, framework_err, impl_err)) { 
        return true; 
       } 
      } 

      /* 
      * Otherwise, pop up an error dialog so the user knows that something bad has happened. Only try and pop up 
      * the dialog if we're attached to a window. When we're going away and no longer have a window, don't bother 
      * showing the user an error. 
      */ 
      if(getWindowToken() != null) { 
       Resources r = getContext().getResources(); 
       int messageId; 

       if(framework_err == MediaPlayer.MEDIA_ERROR_NOT_VALID_FOR_PROGRESSIVE_PLAYBACK) { 
        messageId = R.string.VideoView_error_text_invalid_progressive_playback; 
       } else { 
        messageId = R.string.VideoView_error_text_unknown; 
       } 

       new AlertDialog.Builder(getContext()).setMessage(messageId).setPositiveButton(R.string.VideoView_error_button, new DialogInterface.OnClickListener() { 

        public void onClick(DialogInterface dialog, int whichButton) { 
         /* 
         * If we get here, there is no onError listener, so at least inform them that the video is over. 
         */ 
         if(mOnCompletionListener != null) { 
          mOnCompletionListener.onCompletion(mMediaPlayer); 
         } 
        } 
       }).setCancelable(false).show(); 
      } 
      return true; 
     } 
    }; 

    private MediaPlayer.OnBufferingUpdateListener mBufferingUpdateListener = new MediaPlayer.OnBufferingUpdateListener() { 

     public void onBufferingUpdate(MediaPlayer mp, int percent) { 
      mCurrentBufferPercentage = percent; 
     } 
    }; 

    /** 
    * Register a callback to be invoked when the media file is loaded and ready to go. 
    * 
    * @param l The callback that will be run 
    */ 
    public void setOnPreparedListener(MediaPlayer.OnPreparedListener l) { 
     mOnPreparedListener = l; 
    } 

    /** 
    * Register a callback to be invoked when the end of a media file has been reached during playback. 
    * 
    * @param l The callback that will be run 
    */ 
    public void setOnCompletionListener(OnCompletionListener l) { 
     mOnCompletionListener = l; 
    } 

    /** 
    * Register a callback to be invoked when an error occurs during playback or setup. If no listener is specified, or 
    * if the listener returned false, VideoView will inform the user of any errors. 
    * 
    * @param l The callback that will be run 
    */ 
    public void setOnErrorListener(OnErrorListener l) { 
     mOnErrorListener = l; 
    } 

    SurfaceHolder.Callback mSHCallback = new SurfaceHolder.Callback() { 

     public void surfaceChanged(SurfaceHolder holder, int format, int w, int h) { 
      mSurfaceWidth = w; 
      mSurfaceHeight = h; 
      boolean isValidState = (mTargetState == STATE_PLAYING); 
      boolean hasValidSize = (mVideoWidth == w && mVideoHeight == h); 
      if(mMediaPlayer != null && isValidState && hasValidSize) { 
       if(mSeekWhenPrepared != 0) { 
        seekTo(mSeekWhenPrepared); 
       } 
       start(); 
      } 
     } 

     public void surfaceCreated(SurfaceHolder holder) { 
      mSurfaceHolder = holder; 
      openVideo(); 
     } 

     public void surfaceDestroyed(SurfaceHolder holder) { 
      // after we return from this we can't use the surface any more 
      mSurfaceHolder = null; 
      if(mMediaController != null) 
       mMediaController.hide(); 
      release(true); 
     } 
    }; 

    /* 
    * release the media player in any state 
    */ 
    private void release(boolean cleartargetstate) { 
     if(mMediaPlayer != null) { 
      mMediaPlayer.reset(); 
      mMediaPlayer.release(); 
      mMediaPlayer = null; 
      mCurrentState = STATE_IDLE; 
      if(cleartargetstate) { 
       mTargetState = STATE_IDLE; 
      } 
     } 
    } 

    @Override 
    public boolean onTouchEvent(MotionEvent ev) { 
     if(isInPlaybackState() && mMediaController != null) { 
      toggleMediaControlsVisiblity(); 
     } 
     return false; 
    } 

    @Override 
    public boolean onTrackballEvent(MotionEvent ev) { 
     if(isInPlaybackState() && mMediaController != null) { 
      toggleMediaControlsVisiblity(); 
     } 
     return false; 
    } 

    @Override 
    public boolean onKeyDown(int keyCode, KeyEvent event) { 
     boolean isKeyCodeSupported = keyCode != KeyEvent.KEYCODE_BACK && keyCode != KeyEvent.KEYCODE_VOLUME_UP 
       && keyCode != KeyEvent.KEYCODE_VOLUME_DOWN && keyCode != KeyEvent.KEYCODE_VOLUME_MUTE && keyCode != KeyEvent.KEYCODE_MENU 
       && keyCode != KeyEvent.KEYCODE_CALL && keyCode != KeyEvent.KEYCODE_ENDCALL; 
     if(isInPlaybackState() && isKeyCodeSupported && mMediaController != null) { 
      if(keyCode == KeyEvent.KEYCODE_HEADSETHOOK || keyCode == KeyEvent.KEYCODE_MEDIA_PLAY_PAUSE) { 
       if(mMediaPlayer.isPlaying()) { 
        pause(); 
        mMediaController.show(); 
       } else { 
        start(); 
        mMediaController.hide(); 
       } 
       return true; 
      } else if(keyCode == KeyEvent.KEYCODE_MEDIA_PLAY) { 
       if(! mMediaPlayer.isPlaying()) { 
        start(); 
        mMediaController.hide(); 
       } 
       return true; 
      } else if(keyCode == KeyEvent.KEYCODE_MEDIA_STOP || keyCode == KeyEvent.KEYCODE_MEDIA_PAUSE) { 
       if(mMediaPlayer.isPlaying()) { 
        pause(); 
        mMediaController.show(); 
       } 
       return true; 
      } else { 
       toggleMediaControlsVisiblity(); 
      } 
     } 

     return super.onKeyDown(keyCode, event); 
    } 

    private void toggleMediaControlsVisiblity() { 
     if(mMediaController.isShowing()) { 
      mMediaController.hide(); 
     } else { 
      mMediaController.show(); 
     } 
    } 

    public void start() { 
     if(isInPlaybackState()) { 
      mMediaPlayer.start(); 
      mCurrentState = STATE_PLAYING; 
     } 
     mTargetState = STATE_PLAYING; 
    } 

    public void pause() { 
     if(isInPlaybackState()) { 
      if(mMediaPlayer.isPlaying()) { 
       mMediaPlayer.pause(); 
       mCurrentState = STATE_PAUSED; 
      } 
     } 
     mTargetState = STATE_PAUSED; 
    } 

    public void suspend() { 
     release(false); 
    } 

    public void resume() { 
     openVideo(); 
    } 

    // cache duration as mDuration for faster access 
    public int getDuration() { 
     if(isInPlaybackState()) { 
      if(mDuration > 0) { 
       return mDuration; 
      } 
      mDuration = mMediaPlayer.getDuration(); 
      return mDuration; 
     } 
     mDuration = - 1; 
     return mDuration; 
    } 

    public int getCurrentPosition() { 
     if(isInPlaybackState()) { 
      return mMediaPlayer.getCurrentPosition(); 
     } 
     return 0; 
    } 

    public void seekTo(int msec) { 
     if(isInPlaybackState()) { 
      mMediaPlayer.seekTo(msec); 
      mSeekWhenPrepared = 0; 
     } else { 
      mSeekWhenPrepared = msec; 
     } 
    } 

    public boolean isPlaying() { 
     return isInPlaybackState() && mMediaPlayer.isPlaying(); 
    } 

    public int getBufferPercentage() { 
     if(mMediaPlayer != null) { 
      return mCurrentBufferPercentage; 
     } 
     return 0; 
    } 

    private boolean isInPlaybackState() { 
     return (mMediaPlayer != null && mCurrentState != STATE_ERROR && mCurrentState != STATE_IDLE && mCurrentState != STATE_PREPARING); 
    } 

    public boolean canPause() { 
     return mCanPause; 
    } 

    public boolean canSeekBackward() { 
     return mCanSeekBack; 
    } 

    public boolean canSeekForward() { 
     return mCanSeekForward; 
    } 
} 
+3

你好,從sdk'提取'類是什麼意思,我無法弄清楚如何導入'Metada'和'PolicyManager'? – Copernic

-6

此代碼是VideoView工作過程打開文件探索,去MNT和SD卡那ckick後的按鈕(推文件到設備)存儲在運行按鈕

此代碼是一個主要的data.clock。 xml文件

<LinearLayout 
     android:layout_width="fill_parent" android:layout_height="fill_parent" 
     xmlns:android="http://schemas.android.com/apk/res/android"> 
    <VideoView 
     android:id="@+id/videoView" 
     android:layout_width="300dp" 
     android:layout_height="300dp" /> 

</LinearLayout> 

此代碼是video.java文件

public class VideoActivity extends Activity { 
/** Called when the activity is first created. */ 
    @Override 
    protected void onCreate(Bundle savedInstanceState) { 
     super.onCreate(savedInstanceState); 
     this.setContentView(R.layout.main); 
     VideoView videoView = (VideoView)this.findViewById(R.id.videoView); 
     MediaController mc = new MediaController(this); 
     videoView.setMediaController(mc); 
//videoView.setVideoURI(Uri.parse("http://www.mediafire.com/?trc33d4yma3rkv3.mp4")); 
     videoView.setVideoPath("/sdcard/movie.mp4"); 
     videoView.requestFocus(); 
     videoView.start(); 
    } 
} 

這是清單文件的權限代碼

<uses-permission android:name="android.permission.INTERNET" ></uses-permission> 
+0

你讀過這個問題了嗎? – tasomaniac

2

我有同樣的問題嘗試。您可以使用名爲Field (click for API DOC)的類來手動設置標題對象或任何其他私人表演對象。

VideoView videoView = (VideoView) fl.findViewById(R.id.vidAttachmentPreview); 
videoView.setVideoURI("http://youURL.com"); 

try { 
    Field field = VideoView.class.getDeclaredField("mHeaders"); 
    field.setAccessible(true); 
    field.set(videoView, headerHashMap); 
} catch (Exception e) { 
    e.printStackTrace(); 
} 

// the rest is just standard VideoView stuff 
MediaController mc = new MediaController(LoopThreadActivity.this); 
mc.setAnchorView(videoView); 
videoView.setMediaController(mc); 
videoView.start(); 

我測試了這個,它的工作原理。

+0

Hello Siavash,什麼是headerHashMap? –