最近需求要做一个视频播放功能,在网上查阅了一些资料。大致应该有三种常规实现方式:
1 调用系统默认的播放器来播放。
2 使用VideoView来进行播放。
3 使用MediaPlayer在SurfaceView中进行播放。
查询了一些资料之后发现用SurfaceView的这种方法会比较好。
经过学习之后,写了个demo并对SurfaceView和MediaView进行学习总结。
下方是demo源码:
public class MainActivity extends AppCompatActivity implements View.OnClickListener {
private MediaPlayer player;
private Button btnPlay, btnPause, btnReplay, btnStop;
private SurfaceView surfaceView;
private SurfaceHolder surfaceHolder;
public static final String PATH = Environment.getExternalStorageDirectory().getAbsolutePath()
+ "/DCIM/Camera/VID_20151201_005910.mp4";
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
btnPlay = (Button) findViewById(R.id.btn_play);
btnPause = (Button) findViewById(R.id.btn_pause);
btnReplay = (Button) findViewById(R.id.btn_replay);
btnStop = (Button) findViewById(R.id.btn_stop);
surfaceView = (SurfaceView) findViewById(R.id.sv_video);
btnPlay.setOnClickListener(this);
btnPause.setOnClickListener(this);
btnReplay.setOnClickListener(this);
btnStop.setOnClickListener(this);
player = new MediaPlayer();
surfaceHolder = surfaceView.getHolder();
surfaceHolder.setFixedSize(180, 144);//设置分辨率
//设置surfaceView不维护自己的缓冲区,而是等待屏幕的渲染引擎将内容推送到用户面前
//不设置为默认
surfaceHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
//SurfaceHolder添加callback来实现
surfaceHolder.addCallback(callback);
}
private Callback callback = new Callback() {
@Override
public void surfaceCreated(SurfaceHolder surfaceHolder) {
resetAndPrepare();
}
@Override
public void surfaceChanged(SurfaceHolder surfaceHolder, int i, int i1, int i2) {}
@Override
public void surfaceDestroyed(SurfaceHolder surfaceHolder) {}
};
private void resetAndPrepare() {
File file = new File(PATH);
if (!file.exists()) {
Toast.makeText(this, "文件不存在", Toast.LENGTH_SHORT).show();
return;
}
try {
player.reset();
player.setAudioStreamType(AudioManager.STREAM_MUSIC);
player.setDisplay(surfaceHolder);
player.setDataSource(PATH);
player.prepare();
} catch (IOException e) {
e.printStackTrace();
}
}
@Override
public void onClick(View view) {
switch (view.getId()) {
case R.id.btn_play:
player.start();
break;
case R.id.btn_pause:
player.pause();
break;
case R.id.btn_replay:
resetAndPrepare();
player.start();
break;
case R.id.btn_stop:
resetAndPrepare();
break;
}
}
@Override
protected void onDestroy() {
super.onDestroy();
if (player != null && player.isPlaying()) {
player.stop();
player.release();
}
}
}
效果图:
这个demo需要加入权限:
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
这里主要的知识点就是SurfaceView和MediaPlayer。
MediaPlayer的知识点:
1)获得MediaPlayer实例:
1. MediaPlayer player = new MediaPlayer();
2. MediaPlayerplayer = MediaPlayer.create(this, R.raw.test);//这时就不用调用setDataSource了
2)设置要播放源:
MediaPlayer要播放的文件主要包括3个来源:
1. 用户在应用中事先自带的resource资源
例如:MediaPlayer.create(this, R.raw.test);
2. 存储在SD卡或其他文件路径下的媒体文件
例如:mp.setDataSource("/sdcard/test.mp3");
3. 网络上的媒体文件
例如:mp.setDataSource("http://www.citynorth.cn/music/confucius.mp3");
第二第三中方法都用到了MediaPlayer的setDataSource方法,该方法一共有4中传参方式:
setDataSource (String path)
setDataSource (FileDescriptor fd)
setDataSource (Context context, Uri uri)
setDataSource (FileDescriptor fd, long offset, long length)
3)对播放器的主要控制方法:
Android通过控制播放器的状态的方式来控制媒体文件的播放,其中:
prepare()&prepareAsync() 提供了同步和异步两种方式设置播放器进入prepare状态,需要注意的是,如果MediaPlayer实例是由create方法创建的,那么第一次启动播放前不需要再调用prepare()了,因为create方法里已经调用过了。
start() 播放视频。
pause() 暂停播放,
stop()停止播放。
seekTo() 定位方法,可以让播放器从指定的位置开始播放,需要注意的是该方法是个异步方法,也就是说该方法返回时并不意味着定位完成,尤其是播放的网络文件,真正定位完成时会触发OnSeekComplete.onSeekComplete(),如果需要是可以调用setOnSeekCompleteListener(OnSeekCompleteListener)设置监听器来处理的。
release() 释放播放器占用的资源,一旦确定不再使用播放器时应当尽早调用它释放资源。
reset() 可以使播放器从Error状态中恢复过来,重新会到Idle状态。
4)设置播放器的监听器:
MediaPlayer提供了一些设置不同监听器的方法来更好地对播放器的工作状态进行监听,以期及时处理各种情况,
如: setOnCompletionListener(MediaPlayer.OnCompletionListener listener)、
setOnErrorListener(MediaPlayer.OnErrorListener listener)等,设置播放器时需要考虑到播放器可能出现的情况设置好监听和处理逻辑,以保持播放器的健壮性。
参考文章:http://blog.csdn.net/ddna/article/details/5176233