Android学习笔记----关于MediaPlayer和SurfaceView的视频播放
第一次接触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);
接下来就是播放之类的了。