Android使用VideoView播放本地视频和youtube视频

其中播放youtube视频的核心代码借鉴网上开源代码。
代码如下:
Format.java

/**
 * Represents a format in the "fmt_list" parameter
 * Currently, only id is used
 *
 */
public class Format {

    protected int mId;
    
    /**
     * Construct this object from one of the strings in the "fmt_list" parameter
     * @param pFormatString one of the comma separated strings in the "fmt_list" parameter
     */
    public Format(String pFormatString){
        String lFormatVars[] = pFormatString.split("/");
        mId = Integer.parseInt(lFormatVars[0]);
    }
    /**
     * Construct this object using a format id
     * @param pId id of this format
     */
    public Format(int pId){
        this.mId = pId;
    }
    
    /**
     * Retrieve the id of this format
     * @return the id
     */
    public int getId(){
        return mId;
    }
    /* (non-Javadoc)
     * @see java.lang.Object#equals(java.lang.Object)
     */
    @Override
    public boolean equals(Object pObject) {
        if(!(pObject instanceof Format)){
            return false;
        }
        return ((Format)pObject).mId == mId;
    }
}


VideoStream.java

import java.util.HashMap;
import java.util.Map;
 
/**
 * Represents a video stream
 *
 */
public class VideoStream {
    
    protected String mUrl;
    
    /**
     * Construct a video stream from one of the strings obtained  
     *     from the "url_encoded_fmt_stream_map" parameter if the video_info  
     * @param pStreamStr - one of the strings from "url_encoded_fmt_stream_map"
     */
    public VideoStream(String pStreamStr){
        String[] lArgs=pStreamStr.split("&");
        Map<String,String> lArgMap = new HashMap<String, String>();
        for(int i=0; i<lArgs.length; i++){
            String[] lArgValStrArr = lArgs[i].split("=");
            if(lArgValStrArr != null){
                if(lArgValStrArr.length >= 2){
                    lArgMap.put(lArgValStrArr[0], lArgValStrArr[1]);
                }
            }
        }
        mUrl = lArgMap.get("url");
    }
    public String getUrl(){
        return mUrl;
    }
}


YouTubeUtility.java

import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.net.URLDecoder;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Map;
 
import org.apache.http.HttpResponse;
import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.impl.client.DefaultHttpClient;
 
public class YouTubeUtility {
    
    private static final String YOUTUBE_VIDEO_INFORMATION_URL = "http://www.youtube.com/get_video_info?&video_id=";
    /**
     * Calculate the YouTube URL to load the video.  Includes retrieving a token that YouTube
     * requires to play the video.
     *  
     * @param pYouTubeFmtQuality quality of the video.  17=low, 18=high
     * @param bFallback whether to fallback to lower quality in case the supplied quality is not available
     * @param pYouTubeVideoId the id of the video
     * @return the url string that will retrieve the video
     * @throws IOException
     * @throws ClientProtocolException
     * @throws UnsupportedEncodingException
     */
    public static String calculateYouTubeUrl(String pYouTubeFmtQuality, boolean pFallback,
            String pYouTubeVideoId) throws IOException,
            ClientProtocolException, UnsupportedEncodingException {
 
        String lUriStr = null;
        HttpClient lClient = new DefaultHttpClient();
        
        HttpGet lGetMethod = new HttpGet(YOUTUBE_VIDEO_INFORMATION_URL +  
                                         pYouTubeVideoId);
        
        HttpResponse lResp = null;
 
        lResp = lClient.execute(lGetMethod);
            
        ByteArrayOutputStream lBOS = new ByteArrayOutputStream();
        String lInfoStr = null;
            
        lResp.getEntity().writeTo(lBOS);
        lInfoStr = new String(lBOS.toString("UTF-8"));
        
        String[] lArgs=lInfoStr.split("&");
        Map<String,String> lArgMap = new HashMap<String, String>();
        for(int i=0; i<lArgs.length; i++){
            String[] lArgValStrArr = lArgs[i].split("=");
            if(lArgValStrArr != null){
                if(lArgValStrArr.length >= 2){
                    lArgMap.put(lArgValStrArr[0], URLDecoder.decode(lArgValStrArr[1]));
                }
            }
        }
        
        //Find out the URI string from the parameters
        
        //Populate the list of formats for the video
        String lFmtList = URLDecoder.decode(lArgMap.get("fmt_list"));
        ArrayList<Format> lFormats = new ArrayList<Format>();
        if(null != lFmtList){
            String lFormatStrs[] = lFmtList.split(",");
            
            for(String lFormatStr : lFormatStrs){
                Format lFormat = new Format(lFormatStr);
                lFormats.add(lFormat);
            }
        }
        
        //Populate the list of streams for the video
        String lStreamList = lArgMap.get("url_encoded_fmt_stream_map");
        if(null != lStreamList){
            String lStreamStrs[] = lStreamList.split(",");
            ArrayList<VideoStream> lStreams = new ArrayList<VideoStream>();
            for(String lStreamStr : lStreamStrs){
                VideoStream lStream = new VideoStream(lStreamStr);
                lStreams.add(lStream);
            }    
            
            //Search for the given format in the list of video formats
            // if it is there, select the corresponding stream
            // otherwise if fallback is requested, check for next lower format
            int lFormatId = Integer.parseInt(pYouTubeFmtQuality);
            
            Format lSearchFormat = new Format(lFormatId);
            while(!lFormats.contains(lSearchFormat) && pFallback ){
                int lOldId = lSearchFormat.getId();
                int lNewId = getSupportedFallbackId(lOldId);
                
                if(lOldId == lNewId){
                    break;
                }
                lSearchFormat = new Format(lNewId);
            }
            
            int lIndex = lFormats.indexOf(lSearchFormat);
            if(lIndex >= 0){
                VideoStream lSearchStream = lStreams.get(lIndex);
                lUriStr = lSearchStream.getUrl();
            }
            
        }        
        //Return the URI string. It may be null if the format (or a fallback format if enabled)
        // is not found in the list of formats for the video
        return lUriStr;
    }
 
    public static int getSupportedFallbackId(int pOldId){
        final int lSupportedFormatIds[] = {13,  //3GPP (MPEG-4 encoded) Low quality  
                                          17,  //3GPP (MPEG-4 encoded) Medium quality  
                                          18,  //MP4  (H.264 encoded) Normal quality
                                          22,  //MP4  (H.264 encoded) High quality
                                          37   //MP4  (H.264 encoded) High quality
                                          };
        int lFallbackId = pOldId;
        for(int i = lSupportedFormatIds.length - 1; i >= 0; i--){
            if(pOldId == lSupportedFormatIds[i] && i > 0){
                lFallbackId = lSupportedFormatIds[i-1];
            }            
        }
        return lFallbackId;
    }
} 


播放代码:

    /** 弹出视频的Layout容器 */
    private RelativeLayout popUpVideoLayout;
    /** 弹出视频播放器 */
    private VideoView popUpVideoView;
    /** 视频是否执行的监控线程的执行标志位 */
    private int vedioThreadProcess;
    /** 是否改变isAutoOrientation的标志位
     * 如果改变了,在视频关闭时要改回来;如果没有改变则不需要改变回来 */
    private boolean hasChangedAutoOrientation = false;
    /** 视频文件已经加载完毕 */
    private boolean hasVideoPrepared = false;
    
    public class VideoCtlHandler extends Handler {
        @Override
        public void handleMessage(Message msg) {
            // TODO Auto-generated method stub
            //super.handleMessage(msg);
            switch (msg.what) {
            case 83 :
                // 当视频正在播放状态时,不显示播放和关闭按钮
                Log.e("msg.what", String.valueOf(msg.what));
                if (CTplayBtn.getVisibility() == View.VISIBLE
                        && CTcloseBtn.getVisibility() == View.VISIBLE) {
                    CTplayBtn.setVisibility(View.GONE);
                    CTcloseBtn.setVisibility(View.GONE);
                    Log.e("CTplayBtn&CTcloseBtn", "GONE");                    
                }
                break;
            case 38 :
                // 当视频在没有播放的状态时,显示播放和关闭按钮
                if (CTplayBtn.getVisibility() == View.GONE
                        && CTcloseBtn.getVisibility() == View.GONE) {
                CTplayBtn.setVisibility(View.VISIBLE);
                CTcloseBtn.setVisibility(View.VISIBLE);
                Log.e("CTplayBtn&CTcloseBtn", "VISIBLE");
                }
                break;
            }
        }
      }
    
    /**
     * 关闭当前播放弹出视窗中播放的视频(单击播放的视频).
     * */
    private void closePopUpVideo() {
        if (popUpVideoView != null) {
            if (hasChangedAutoOrientation ==  true) {
                switchAutoOrientation(this, true);                
            }
            vedioThreadProcess = 0;
            popUpVideoView.stopPlayback();
            popUpVideoView.setMediaController(null);
            popUpVideoView = null;
            popUpVideoLayout.removeAllViews();
            mLytMain.removeView(popUpVideoLayout);
        }
    }
    
    public static void switchAutoOrientation(XXXXXXXNew ap, boolean toggleSetting) {
        if (toggleSetting)
            isAutoOrientation = !isAutoOrientation;

        if (getAutoOrientation() == true) {
            ap.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_SENSOR);
        } else {
            // setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_USER);
            if (ap.getDisplaySize().isLandscape())
                ap
                        .setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);
            else
                ap
                        .setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
        }
    }
    /**
     * 弹出窗体显示本机视频
     * */
    private void popUpLocalVideo(String data, String sMediaPath, String youtubeUrl, AbsoluteLayout.LayoutParams params,
            boolean isYoutube) {
        if (!isYoutube) {
            if (!DRMControl.unzipFile(data, sMediaPath)) {
                Log.i("Err", "------------------unzipFile media failed !");
                return;
            }            
        }
        hasVideoPrepared = false;
        // 如果已经有视频在播放,则关闭
        closePopUpVideo();
        // 在视频播放时控制pad屏幕不可旋转
        if (isAutoOrientation == true) {
            switchAutoOrientation(this, true);
            hasChangedAutoOrientation = true;
        } else {
            switchAutoOrientation(this, false);
            hasChangedAutoOrientation = false;
        }

        vHandler = new VideoCtlHandler();
        // 添加视频播放器
        popUpVideoLayout = new RelativeLayout(context);
        popUpVideoView = new VideoView(context);
        RelativeLayout.LayoutParams textParams2 = new RelativeLayout.LayoutParams(
                RelativeLayout.LayoutParams.FILL_PARENT,
                RelativeLayout.LayoutParams.FILL_PARENT);
        textParams2.addRule(RelativeLayout.CENTER_IN_PARENT);
        popUpVideoLayout.addView(popUpVideoView, textParams2);
        
        // 添加播放按钮
        CTplayBtn = new ImageButton(context);
        CTplayBtn.setBackgroundResource(R.drawable.play);
        RelativeLayout.LayoutParams playBtnParams = new RelativeLayout.LayoutParams(
                RelativeLayout.LayoutParams.WRAP_CONTENT,
                RelativeLayout.LayoutParams.WRAP_CONTENT);
        playBtnParams.addRule(RelativeLayout.CENTER_VERTICAL);
        if (this.getResources().getConfiguration().orientation == Configuration.ORIENTATION_PORTRAIT) {
            playBtnParams.leftMargin = mScreenRect.width()/2 - 100;
        } else {
            playBtnParams.leftMargin = mScreenRect.width()/8 + 50;
        }
        popUpVideoLayout.addView(CTplayBtn, playBtnParams);
        CTplayBtn.setVisibility(View.GONE);
        CTplayBtn.setOnClickListener(new OnClickListener(){

            @Override
            public void onClick(View v) {
                // TODO Auto-generated method stub
                popUpVideoView.setMediaController(new MediaController(context));
                popUpVideoView.start();
                CTplayBtn.setVisibility(View.GONE);
                CTcloseBtn.setVisibility(View.GONE);
            }
            
        });
        
        // 添加关闭按钮
        CTcloseBtn = new ImageButton(context);
        CTcloseBtn.setBackgroundResource(R.drawable.pause);
        RelativeLayout.LayoutParams closeBtnParams = new RelativeLayout.LayoutParams(
                RelativeLayout.LayoutParams.WRAP_CONTENT,
                RelativeLayout.LayoutParams.WRAP_CONTENT);
        closeBtnParams.addRule(RelativeLayout.CENTER_VERTICAL);
        if (this.getResources().getConfiguration().orientation == Configuration.ORIENTATION_PORTRAIT) {
            closeBtnParams.leftMargin = mScreenRect.width()/2 + 100;
        } else {
            closeBtnParams.leftMargin = mScreenRect.width()*3/8 - 50;;
        }
        popUpVideoLayout.addView(CTcloseBtn, closeBtnParams);
        CTcloseBtn.setVisibility(View.GONE);
        CTcloseBtn.setOnClickListener(new OnClickListener(){

            @Override
            public void onClick(View v) {
                // TODO Auto-generated method stub
                closePopUpVideo();
            }
            
        });
        if (!isYoutube) {
            // 播放本地视频
            String sPath = sMediaPath + data;
            popUpVideoView.setVideoPath(sPath);
        } else {
            // 播放youtube视频
            String lUriStr = "";
            try{
                 lUriStr = YouTubeUtility.calculateYouTubeUrl("18", true, getVideoId(youtubeUrl));
            } catch (Exception e) {
                
            }
            if ("".equals(lUriStr)) {
                return;
            }
            popUpVideoView.setVideoURI(Uri.parse(lUriStr));
        }
        MediaController mediaController = new MediaController(this);
        mediaController.setAnchorView(popUpVideoView);
        popUpVideoView.setMediaController(mediaController);
        //videoView.requestFocus();
        popUpVideoView.setOnPreparedListener(new OnPreparedListener() {
            public void onPrepared(MediaPlayer mp) {
                mp.start();
                hasVideoPrepared = true;
            }
        });
        
        // 视频播放状态监控线程
        vedioThreadProcess = 1;
        vThread = new Thread() {
            @Override
            public void run() {
                while (vedioThreadProcess == 1) {
                    try{
                        sleep(700);                        
                    } catch (Exception e) {
                        
                    }
                    // 当视频正在播放状态时
                    if (popUpVideoView != null && popUpVideoView.getParent() != null
                            && hasVideoPrepared && popUpVideoView.isPlaying()) {
                        Log.e("videoView", "is playing");
                        vHandler.sendEmptyMessage(83);
                    }
                    // 当视频在非播放状态时
                    if (popUpVideoView != null && popUpVideoView.getParent() != null
                            && hasVideoPrepared && !popUpVideoView.isPlaying()) {
                        Log.e("videoView", "is not playing");
                        vHandler.sendEmptyMessage(38);
                    }
                }
            }
        };
        vThread.start();
        
        // 视频播放器点击事件,停止视频播放并且显示播放和关闭按钮
        popUpVideoView.setOnTouchListener(new OnTouchListener() {

            @Override
            public boolean onTouch(View v, MotionEvent event) {
                // TODO Auto-generated method stub
                switch (event.getAction()) {
                case MotionEvent.ACTION_DOWN :{
                    popUpVideoView.pause();
                    // popUpVideoView.setMediaController(null);
                    CTplayBtn.setVisibility(View.VISIBLE);
                    CTcloseBtn.setVisibility(View.VISIBLE);
                    break;
                }
                case MotionEvent.ACTION_UP : break;
                case MotionEvent.ACTION_MOVE : return false;
                }
                
                return false;
            }
            
        });
        mLytMain.addView(popUpVideoLayout, params);
    }
posted @ 2012-08-06 12:43  日光之下无新事  阅读(4695)  评论(1编辑  收藏  举报