其中播放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); }