1. 程式人生 > >獲得網路視訊縮圖並且播放

獲得網路視訊縮圖並且播放

</pre><pre name="code" class="java">
</pre><pre name="code" class="java">利用surfacehlder 和mediaplayer  播放網路視訊
import java.io.IOException;

import android.app.Activity;
import android.content.Intent;
import android.graphics.PixelFormat;
import android.media.MediaPlayer;
import android.media.MediaPlayer.OnBufferingUpdateListener;
import android.media.MediaPlayer.OnCompletionListener;
import android.media.MediaPlayer.OnErrorListener;
import android.media.MediaPlayer.OnPreparedListener;
import android.os.Bundle;
import android.util.Log;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
import android.view.View;
import android.widget.ArrayAdapter;
import android.widget.AutoCompleteTextView;
import android.widget.Button;
import android.widget.TextView;
/** 
 * 
 * 
 * SurfaceHolder  
 * 		1. 簡介 : 是 Surface 的控制器, 用於控制 SurfaceView 繪圖, 處理畫布上的動畫, 渲染效果, 大小等;
 * 		2. 常用方法 : 
 * 			-- abstract void addCallback(SurfaceHolder.Callback callback) : 新增一個 SurfaceHolder.Callback 介面物件, 監聽 Surface 的開始結束繪製大小改變事件;
 * 			-- abstract Canvas lockCanvas() : 鎖定畫布, 可以獲得 Canvas 物件, 之後就可以在 Canvas 上繪圖了;
 * 
 * SurfaceHolder.Callback介面 : 
 * 		1. Surface 繪圖邊界 : 所有的繪圖工作都在 Surface 建立之後才能進行, 在 Surface 銷燬之前結束;
 * 		2. Callback 介面對應的 Surface 邊界 : surfaceCreated() 方法在開始繪製時回撥, surfaceDestroyed() 在 Surface 銷燬前回調;
 * 		3. 該介面中的方法 : 
 * 			-- surfaceChanged() : 在 Surface 大小改變時回撥;
 * 			-- surfaceCreated() : 在 Surface 建立時回撥;
 * 			--  () : 在 Surface 銷燬時回撥;
 * 
 * @author octopus 
 *
 */
public class MPlayer extends Activity implements SurfaceHolder.Callback {

//	private AutoCompleteTextView url;							/* 地址輸入框, 帶自動提示功能 */
	private SurfaceView surface_view;							/* 播放視訊載體 */
	private TextView status;									/* 顯示播放狀態 */
	private Button play;										/* 播放按鈕 */
	private Button pause;										/* 暫停按鈕 */
	private Button reset;										/* 重放按鈕 */
	private Button stop;										/* 停止按鈕 */
	
	private MediaPlayer mediaPlayer;							/* 播放器 */
	private SurfaceHolder surface_holder; 						/* Surface 控制器 */
	
	private boolean isStartPlaying;		/* 是否開始了播放 */
    private int vedioPosition;         /* 接收intent從MainActivity傳過來的需要播放的視訊URL*/
	
	
	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.activity_mplayer);
		Intent intent1=getIntent();//getIntent將該專案中包含的原始intent檢索出來,將檢索出來的intent賦值給一個Intent型別的變數intent  
		vedioPosition=intent1.getExtras().getInt("vedioUrl");
		initViews();
		initData();
	}

	/**
	 * 初始化成員變數中的元件變數
	 */
	private void initViews() {
		/* 通過 findViewById 獲取相關方法 */
//		url = (AutoCompleteTextView) findViewById(R.id.url);
		surface_view = (SurfaceView) findViewById(R.id.surface_view);
		
		status = (TextView) findViewById(R.id.status);
		play = (Button) findViewById(R.id.play);
		pause = (Button) findViewById(R.id.pause);
		reset = (Button) findViewById(R.id.reset);
		stop = (Button) findViewById(R.id.stop);
		/* 使視窗支援透明度, 把當前 Activity 視窗設定成透明, 設定了該選項就可以使用 setAlpha 等函式設定視窗透明度 */
		getWindow().setFormat(PixelFormat.TRANSPARENT);
	}	
	/**
	 * 初始化相關資料變數
	 */
	private void initData() {
		/* 獲取並設定 SurfaceHolder 物件 */
		surface_holder = surface_view.getHolder();						/* 根據 SurfaceView 元件, 獲取 SurfaceHolder 物件 */
		surface_holder.addCallback(this); 								/* 為 SurfaceHolder 設定回撥函式, 即 SurfaceHolder.Callback 子類物件 */
		surface_holder.setFixedSize(160, 128);							/* 設定視訊大小比例 */
		surface_holder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);/* 設定視訊型別 */	
	}	
	/**
	 * 設定點選事件
	 * @param view
	 */
	public void onClick(View view) {
		int id = view.getId();
		switch (id) {
		case R.id.play:
			playVideo(VedioImages.imageThumbUrls[vedioPosition].toString());
			break;
			
		case R.id.pause:
			if(mediaPlayer != null){
				mediaPlayer.pause();
				status.setText("暫停");
			}
			break;
			
		case R.id.reset:
			if(mediaPlayer != null){
				mediaPlayer.seekTo(0);
				mediaPlayer.start();
				status.setText("播放中");
			}
			break;
	
		case R.id.stop:
			if(mediaPlayer != null){
				mediaPlayer.stop();
				mediaPlayer.release();
				isStartPlaying = false;
				status.setText("停止");
			}
			break;

		default:
			break;
		}
	}
	
	/**
	 * 播放網路視訊
	 * a. 建立並配置 MediaPlayer 物件 (音量, SurfaceHolder)
	 * b. 為 MediaPlayer 設定錯誤監聽器, 緩衝進度監聽器, 播放完畢監聽器, 準備完畢監聽器
	 * c. 未 MediaPlayer 設定資料來源
	 * d. 呼叫 prepare() 進入 Prapared 狀態
	 * e. 呼叫 start() 進入 Started 狀態
	 * 
	 * @param dataSource 播放視訊的網路地址
	 */
	private void playVideo(final String dataSource) {
		
		/* 點選播放有兩種情況 
		 * a. 第一次點選 : 需要初始化 MediaPlayer 物件, 設定監聽器
		 * b. 第二次點選 : 只需要 呼叫 mediaPlayer 的 start() 方法
		 * 兩種情況通過 isStartPlaying 點選時間判斷 */
		
		if(isStartPlaying){								/* 如果已經開始了播放, 就直接開始播放 */
			mediaPlayer.start();
		}else{											/* 如果是第一次開始播放, 需要初始化 MediaPlayer 設定監聽器等操作 */
			mediaPlayer = new MediaPlayer(); 			/* 建立 MediaPlayer 物件 */
			mediaPlayer.setAudioStreamType(2); 			/* 設定播放音量 */
			mediaPlayer.setDisplay(surface_holder); 	/* 設定播放載體 */	
			
			/* 設定 MediaPlayer 錯誤監聽器, 如果出現錯誤就會回撥該方法列印錯誤程式碼 */
			mediaPlayer.setOnErrorListener(new OnErrorListener() {
				@Override
				public boolean onError(MediaPlayer arg0, int what, int extra) {
					System.out.println("MediaPlayer 出現錯誤 what : " + what + " , extra : " + extra);
					return false;
				}
			});
			
			/* 設定緩衝進度更新監聽器 */
			mediaPlayer.setOnBufferingUpdateListener(new OnBufferingUpdateListener() {
				@Override
				public void onBufferingUpdate(MediaPlayer arg0, int percent) {
					/* 列印緩衝的百分比, 如果緩衝 */
					System.out.println("緩衝了的百分比 : " + percent + " %");
				}
			});
			
			/* 設定播放完畢監聽器 */
			mediaPlayer.setOnCompletionListener(new OnCompletionListener() {
				@Override
				public void onCompletion(MediaPlayer arg0) {
					Log.i("tag","播放完畢了");
					System.out.println("播放完畢了");
					status.setText("播放完畢");
				}
			});
			
			/* 設定準備完畢監聽器 */
			mediaPlayer.setOnPreparedListener(new OnPreparedListener() {
				@Override
				public void onPrepared(MediaPlayer arg0) {
					Log.i("tag","準備完畢");
					System.out.println("準備完畢");
					/* 設定播放狀態 */
					status.setText("播放中");
				}
			});
			new Thread(){
				public void run() {
					try {
						
						System.out.println("設定資料來源");
						mediaPlayer.setDataSource(dataSource);
						mediaPlayer.prepare();
						/* 列印播放視訊的時長 */
						Log.i("tag","視訊播放長度 : " + mediaPlayer.getDuration());
						System.out.println("視訊播放長度 : " + mediaPlayer.getDuration());
						mediaPlayer.start();
					} catch (IllegalStateException e) {
						e.printStackTrace();
					} catch (IOException e) {
						e.printStackTrace();
					}
				};
			}.start();
			/* 設定 MediaPlayer 開始播放標識為 true */
			isStartPlaying = true;
			/* 設定播放狀態 */
			status.setText("正在緩衝");
		}
	}
	/**
	 * 在 Surface 大小發生改變的時候回撥
	 * 實現的 SurfaceHolder.Callback 介面方法
	 */
	@Override
	public void surfaceChanged(SurfaceHolder arg0, int arg1, int arg2, int arg3) {
		Log.i("tag","SurfaceHolder.Callback.surfaceChanged : Surface 大小發生改變");
		System.out.println("SurfaceHolder.Callback.surfaceChanged : Surface 大小發生改變");
	}
	/**
	 * 在 Surface 建立的時候回撥, 一般在該方法中開始繪圖
	 * 實現的 SurfaceHolder.Callback 介面方法
	 */
	@Override
	public void surfaceCreated(SurfaceHolder arg0) {
		Log.i("tag","SurfaceHolder.Callback.surfaceCreated : Surface 開始建立");
		System.out.println("SurfaceHolder.Callback.surfaceCreated : Surface 開始建立");
	}
	/**
	 * 在 Surface 銷燬之前回調, 在該方法中停止渲染執行緒, 釋放相關資源
	 * 實現的 SurfaceHolder.Callback 介面方法
	 */
	@Override
	public void surfaceDestroyed(SurfaceHolder arg0) {
		Log.i("tag","SurfaceHolder.Callback.surfaceDestroyed : Surface 銷燬");
		System.out.println("SurfaceHolder.Callback.surfaceDestroyed : Surface 銷燬");
	}
	@Override
	protected void onDestroy() {
		if(mediaPlayer != null)
			mediaPlayer.release();
		super.onDestroy();
	}
}