28、從頭學Android之多媒體--使用MediaPlayer和SurfaceView播放視頻

應用場景:

使用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() {		
			@Override
			public void surfaceDestroyed(SurfaceHolder holder) {
		
			}
		
			@Override
			public void surfaceCreated(SurfaceHolder holder) {
				if (position>0) {
					try {
						//開始播放
						play();
						//並直接從指定位置開始播放
						mediaPlayer.seekTo(position);
						position=0;						
					} catch (Exception e) {
						// TODO: handle exception
					}
				}
			}			
			@Override
			public void surfaceChanged(SurfaceHolder holder, int format, int width,
					int height) {

			}
		});		
	}
	@Override
	public 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;
		}

	}
	@Override
	protected 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");
			//把視頻畫面輸出到SurfaceView
			mediaPlayer.setDisplay(surfaceView.getHolder());
			mediaPlayer.prepare();
			//播放
			mediaPlayer.start();		
		} catch (Exception e) {
			// TODO: handle exception
		}
	}
}

 如需轉載引用請註明出處:http://blog.csdn.net/jiahui524

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章