2011-10-03 46 views
10

Tôi đang cố gắng sử dụng android.widget.VideoView để truyền trực tuyến nội dung. Tôi cần đảm bảo rằng khi sử dụng setVideoURI (Uri), VideoView sẽ bao gồm Cookie từ các cuộc gọi HttpClient trước đó. Tôi thấy trong nguồn có setVideoUri (Uri, Tiêu đề) nhưng điều này có chú thích JavaDoc @hide và sẽ không biên dịch.VideoView với Cookie (hoặc Tiêu đề)

Vì vậy, dù sao để chuyển cookie hoặc tiêu đề bằng các yêu cầu HTTP được thực hiện bởi VideoView?

Cảm ơn.

+0

# marc2112 vui lòng xem câu trả lời của tôi – Siavash

Trả lời

8

Trích xuất lớp học VideoViewSiêu dữ liệu từ SDK. Sau đó, bạn sẽ có thể gọi số setVideoURI(Uri uri, Map<String, String> headers) trên lớp VideoView của riêng bạn.

Lưu ý rằng siêu dữ liệu không được trích vì mp.getMetadata(MediaPlayer.METADATA_ALL, MediaPlayer.BYPASS_METADATA_FILTER) không truy cập được nhưng bạn có thể thử với 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

Xin chào, Bạn có ý nghĩa gì bởi các lớp 'trích xuất' từ sdk' vì tôi không thể tìm ra cách nhập' Metada' và 'PolicyManager'? – Copernic

-6

Mã này là quá trình làm việc VideoView mở tập tin khám phá, đi đến một mnt và sdcard sau ckick rằng nút (đẩy một tập tin vào thiết bị) lưu trữ các data.clock vào nút chạy

Mã này là một chính. tập tin 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> 

mã này là video.java tập tin

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(); 
    } 
} 

Đây là file manifest đang cho phép

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

bạn đã đọc câu hỏi chưa? – tasomaniac

2

tôi đã cùng một vấn đề. Bạn có thể tự đặt đối tượng tiêu đề hoặc bất kỳ feild riêng tư nào khác cho vấn đề đó, sử dụng một lớp có tên là 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(); 

Tôi đã thử nghiệm tính năng này và hoạt động.

+0

Xin chào Siavash, headerHashMap là gì? –

Các vấn đề liên quan