應用情境:
使用VideoView播放視頻簡單、方便,但除此之外,我們還可以利用MediaPlayer用來播放視頻。但是我們知道MediaPlayer主要用於播放音頻,它是沒有提供輸出映像的輸出介面,這時我們就用到了SurfaceView控制項,將它與MediaPlayer結合起來,就能達到了視頻的輸出了。首先來了SurfaceView這個控制項類
SurfaceView類
構造方法
方法名稱 |
描述 |
public SurfaceView(Context context) |
通過Context建立SurfaceView對象 |
public SurfaceView(Context context, AttributeSet attrs) |
通過Context對象和AttributeSet建立SurfaceView對象 |
public SurfaceView(Context context, AttributeSet attrs, int defStyle) |
通過Context對象和AttributeSet建立並可以指定樣式,SurfaceView對象 |
常用方法
方法名稱 |
描述 |
public SurfaceHolder getHolder () |
得到SurfaceHolder對象用於管理SurfaceView |
public void setVisibility (int visibility) |
設定是否可見,其值可以是VISIBLE, INVISIBLE, GONE. |
SurfaceHolder
它是一個介面,用於管理SurfaceView。裡面有兩個常用的內部介面SurfaceHolder.Callback,SurfaceHolder.Callback2而Callback2是實現於Callback的
常用方法
方法名稱 |
描述 |
public abstract void addCallback (SurfaceHolder.Callback callback) |
添加一個Callback對象監聽SurfaceView的變化 |
public abstract void removeCallback (SurfaceHolder.Callback callback) |
移除Callback |
public abstract void setType (int type) |
設定SurfaceView的控制方式 |
public abstract Canvas lockCanvas () |
鎖定整個SurfaceView對象,擷取該Surface上的Canvas |
public abstract Canvas lockCanvas (Rect dirty) |
鎖定SurfaceView上Rect劃分的地區,擷取該Surface上的Canvas |
public abstract void unlockCanvasAndPost (Canvas canvas) |
調用該方法,之前所繪製的圖形還處於緩衝之中,下一次的lockCanvas()方法鎖定的地區可能會“遮擋”它 |
SurfaceHolder.CallBack
在Callback裡有三個抽象方法
方法名稱 |
描述 |
public abstract void surfaceChanged (SurfaceHolder holder, int format, int width, int height) |
SurfaceView改變時觸發 |
public abstract void surfaceCreated (SurfaceHolder holder) |
SurfaceView建立時觸發 |
public abstract void surfaceDestroyed (SurfaceHolder holder) |
SurfaceView銷毀時觸發 |
如何理解這幾個類或者介面之間的關係?
這樣理解:
SurfaceView它用於顯示,SurfaceHolder就是用於用來管理這個顯示的SurfaceView對象的,但在SurfaceHolder是怎麼樣去管理這個對象的呢?這就用到了SurfceHolder.addCallback()方法添加一個SurfaceHolder介面的內部介面的三個抽象方法用於管理或者說是用於監聽SurfaceView。這樣就達到了管理SurfaceView的目的。
執行個體:使用MediaPlayer與SurfaceView播放視頻
實現效果:
實現步驟:
1) 建立MediaPlayer對象,並設定載入的視頻檔案(setDataSource())
2) 在介面布局檔案中定義SurfaceView控制項
3) 通過MediaPlayer.setDisplay(SurfaceHolder sh)來指定視頻畫面輸出到SurfaceView之上
4) 通過MediaPlayer的其他一些方法用於播放視頻
代碼實現:
布局檔案:main.xml
<?xml version="1.0" encoding="utf-8"?><LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="fill_parent" android:layout_height="fill_parent" android:orientation="vertical" > <SurfaceView android:id="@+id/surfaceView" android:layout_width="fill_parent" android:layout_height="360px" /> <LinearLayout android:layout_width="fill_parent" android:layout_height="wrap_content" android:gravity="center_horizontal" android:orientation="horizontal" > <ImageButton android:id="@+id/btnplay" android:layout_width="wrap_content" android:layout_height="wrap_content" android:src="@drawable/play" /> <ImageButton android:id="@+id/btnpause" android:layout_width="wrap_content" android:layout_height="wrap_content" android:src="@drawable/pause" /> <ImageButton android:id="@+id/btnstop" android:layout_width="wrap_content" android:layout_height="wrap_content" android:src="@drawable/stop" /> </LinearLayout></LinearLayout>
Activity代碼
package com.jiahui.surfaceview;import android.app.Activity;import android.media.AudioManager;import android.media.MediaPlayer;import android.os.Bundle;import android.view.SurfaceHolder;import android.view.SurfaceHolder.Callback;import android.view.SurfaceView;import android.view.View;import android.view.View.OnClickListener;import android.widget.Button;import android.widget.ImageButton;public class SurfaceViewVideoDemoActivity extends Activity implements OnClickListener{ImageButton btnplay, btnstop, btnpause;SurfaceView surfaceView;MediaPlayer mediaPlayer;int position;public void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.main);btnplay=(ImageButton)this.findViewById(R.id.btnplay);btnstop=(ImageButton)this.findViewById(R.id.btnplay);btnpause=(ImageButton)this.findViewById(R.id.btnplay);btnstop.setOnClickListener(this);btnplay.setOnClickListener(this);btnpause.setOnClickListener(this);mediaPlayer=new MediaPlayer();surfaceView=(SurfaceView) this.findViewById(R.id.surfaceView);//設定SurfaceView自己不管理的緩衝區surfaceView.getHolder().setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);surfaceView.getHolder().addCallback(new Callback() {@Overridepublic void surfaceDestroyed(SurfaceHolder holder) {}@Overridepublic void surfaceCreated(SurfaceHolder holder) {if (position>0) {try {//開始播放play();//並直接從指定位置開始播放mediaPlayer.seekTo(position);position=0;} catch (Exception e) {// TODO: handle exception}}}@Overridepublic void surfaceChanged(SurfaceHolder holder, int format, int width,int height) {}});}@Overridepublic void onClick(View v) {switch (v.getId()) {case R.id.btnplay:play();break;case R.id.btnpause:if (mediaPlayer.isPlaying()) {mediaPlayer.pause();}else{mediaPlayer.start();}break;case R.id.btnstop:if (mediaPlayer.isPlaying()) {mediaPlayer.stop();}break;default:break;}}@Overrideprotected void onPause() {//先判斷是否現正播放if (mediaPlayer.isPlaying()) {//如果現正播放我們就先儲存這個播放位置position=mediaPlayer.getCurrentPosition();mediaPlayer.stop();}super.onPause();}private void play() {try {mediaPlayer.reset();mediaPlayer.setAudioStreamType(AudioManager.STREAM_MUSIC);//設定需要播放的視頻mediaPlayer.setDataSource("/mnt/sdcard/movie.3gp");//把視頻畫面輸出到SurfaceViewmediaPlayer.setDisplay(surfaceView.getHolder());mediaPlayer.prepare();//播放mediaPlayer.start();} catch (Exception e) {// TODO: handle exception}}}
如需轉載引用請註明出處:http://blog.csdn.net/jiahui524