第一次接触SurfaceView,就简单写写自己的理解以及从网上看到的东西。
SurfaceView通俗点来说就相当于在Activity的界面中中开辟一块界面用来显示内容。在一个视图层中嵌入一个专用绘画表面,它是可以由用户自定义的。当然它的父类也是View。
SurfaceView与View的区别在哪?
大家都直到View必须在主UI线程中调用,而SurfaceView可以由用户自己来创建线程调用,这就有了一个好处,当你的View界面比较复杂时,你就不会因为长期的占用主线程而导致线程阻塞,某种意义上可一释放线程。
下面我就来说说MediaPlayer和SurfaceView的联合播放视频
SurfaceView在xml文件中的使用就相当于TextView的用法,本身它就是一个组件,主要的一点SurfaceView与SurfaceHolder绑定,并添加callback监听器。
实例如下(借鉴网上的代码s):
package com.edu.video;
import java.io.IOException;
import android.app.Activity;
import android.media.MediaPlayer;
import android.media.MediaPlayer.OnCompletionListener;
import android.media.MediaPlayer.OnErrorListener;
import android.media.MediaPlayer.OnInfoListener;
import android.media.MediaPlayer.OnPreparedListener;
import android.media.MediaPlayer.OnSeekCompleteListener;
import android.media.MediaPlayer.OnVideoSizeChangedListener;
import android.os.Bundle;
import android.util.Log;
import android.view.Display;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
import android.widget.LinearLayout;
public class TestVideoPlayerActivity extends Activity
implements OnCompletionListener,OnErrorListener,
OnInfoListener, SurfaceHolder.Callback,
OnPreparedListener, OnSeekCompleteListener,
OnVideoSizeChangedListener
{
Display currentDisplay;
SurfaceView surfaceView;
SurfaceHolder surfaceHolder;
MediaPlayer mediaPlayer;
int videoWidth = 0;
int videoHeight = 0;
boolean readyToPlayer = false;
public final static String LOGCAT = "CUSTOM_VIDEO_PLAYER";
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
surfaceView = (SurfaceView)findViewById(R.id.surfaceVeiw);
surfaceHolder = surfaceView.getHolder();
surfaceHolder.addCallback(this);
// surfaceHolder.setFixedSize(320,240);
surfaceHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
mediaPlayer = new MediaPlayer();
mediaPlayer.setOnCompletionListener(this);
mediaPlayer.setOnErrorListener(this);
mediaPlayer.setOnPreparedListener(this);
mediaPlayer.setOnSeekCompleteListener(this);
mediaPlayer.setOnVideoSizeChangedListener(this);
String filePath = "/sdcard/video.3gp";
try{
mediaPlayer.setDataSource(filePath);
}catch(IllegalArgumentException e)
{
Log.v(LOGCAT, e.getMessage());
finish();
}catch(IllegalStateException e)
{
Log.v(LOGCAT, e.getMessage());
finish();
}catch(IOException e)
{
Log.v(LOGCAT,e.getMessage());
finish();
}
currentDisplay = getWindowManager().getDefaultDisplay();
}
public boolean onInfo(MediaPlayer arg0, int whatInfo, int extra) {
return false;
}
public boolean onError(MediaPlayer arg0, int arg1, int arg2) {
Log.v(LOGCAT,"onError Called");
return false;
}
public void onCompletion(MediaPlayer mp) {
Log.v(LOGCAT,"onCompletion called");
finish();
}
public void onVideoSizeChanged(MediaPlayer mp, int width, int height) {
Log.v(LOGCAT,"onVideoSizeChanged called");
}
public void onSeekComplete(MediaPlayer mp) {
Log.v(LOGCAT,"onSeekComplete called");
}
public void onPrepared(MediaPlayer mp) {
Log.v(LOGCAT,"onPrepared called");
videoWidth = mp.getVideoWidth();
videoHeight = mp.getVideoHeight();
surfaceView.setLayoutParams(new LinearLayout.LayoutParams(videoWidth,videoHeight));
//mp.prepare();
mp.start();
}
public void surfaceChanged(SurfaceHolder holder, int format, int width,
int height) {
}
public void surfaceCreated(SurfaceHolder holder) {
Log.v(LOGCAT,"suc calles");
mediaPlayer.setDisplay(holder); // 若无此句,只有声音没有图像
try{
mediaPlayer.prepare();
}catch(IllegalStateException e)
{
Log.v(LOGCAT, e.getMessage());
finish();
}catch(IOException e)
{
Log.v(LOGCAT,e.getMessage());
finish();
}
}
public void surfaceDestroyed(SurfaceHolder holder) {
Log.v(LOGCAT,"surfaceDestroyed called");
}
}
开始放了个20M左右的视频,程序无法运行,老是报错,可能是虚拟机内存不足的问题,自己重新拍了一个,问题解决了。
我们来分析一下代码,刚开始绑定了很多监听接口,用于监听MediaPlayer播放过程发生的各种事件,可以有选择的添加(不添加也没什么大问题),
然后主要的就是:
SurfaceView绑定SurfaceHolder
SurfaceHolder = surfaceView.getHolder();
然后添加Callba监听器:
surfaceHolder.addCallback(this);
在准备视频之前mediaPlayer与surfaceHolder连接:
mediaPlayer.setDisplay(surfaceHolder);
接下来就是播放之类的了。