android surfaceview的简单使用,surfaceview_learn

SurfaceView和MediaPlayer学习

该工程采用SurfaceView和MediaPlayer控制本地视频的播放,通过该工程,可以学会SurfaceView和MediaPlayer的基本用法,如:

SurfaceView常用函数有哪些,与MediaPlayer关联起来的方法

MediaPlayer常用函数有哪些,与SurfaceView关联起来的方法

SurfaceView使用时有哪些注意点

SurfaceView核心代码

1. SurfaceView获取

surfaceView = (SurfaceView) findViewById(R.id.surface_view);

2. SurfaceView实现CallBack

surfaceView.getHolder().addCallback(new SurfaceHolder.Callback() {

@Override

public void surfaceCreated(SurfaceHolder surfaceHolder) {

Log.d(TAG, "surfaceCreated: setDisplay");

mediaPlayer.setDisplay(surfaceHolder);//MediaPlayer与SurfaceView关联

if(m_isManToPlay) {

m_isManToPlay = false;

mediaPlayer.start();

} else {

if(current_position != 0) {

mediaPlayer.seekTo(current_position);

}

}

}

@Override

public void surfaceChanged(SurfaceHolder surfaceHolder, int i, int i1, int i2) {

Log.d(TAG, "surfaceChanged: ");

}

@Override

public void surfaceDestroyed(SurfaceHolder surfaceHolder) {//SurfaceView的Surface是画面不在前台时调用

Log.d(TAG, "surfaceDestroyed: "); //TextureView的Surface是画面销毁时调用

}

});

MediaPlayer核心代码

1. 创建MediaPlayer实例

创建时设置播放源,创建完成后,MediaPlayer处于Prepared状态

mediaPlayer = MediaPlayer.create(getApplicationContext(), R.raw.video_test);

只创建实例,随后设置播放源

mediaPlayer = new MediaPlayer();//MediaPlayer处于Idle状态

try {

mediaPlayer.setDataSource(getAssets().openFd("audio_test.mp3"));//MediaPlayer处于Initialized状态

mediaPlayer.prepareAsync();//MediaPlayer处于Preparing状态

} catch (IOException e) {

e.printStackTrace();

}

2. 实现OnPreparedListener

mediaPlayer.setOnPreparedListener(new MediaPlayer.OnPreparedListener() {

@Override

public void onPrepared(MediaPlayer mediaPlayer) {//MediaPlayer处于Prepared状态

Log.d(TAG, "onPrepared: ");

mediaPlayer.seekTo(1);//处理onPrepared时,surface区域黑屏

}

});

3. 开始播放视频

mediaPlayer.start();

4. 暂停播放视频

mediaPlayer.pause();

5. 快进到某一位置

mediaPlayer.seekTo(1);

6. 释放MediaPlayer资源,画面退出时调用

mediaPlayer.release();

常见问题处理

1. 视频播放时,SurfaceView区域黑屏

MediaPlayer设置SurfaceHolder时,该SurfaceHolder未创建,需要在surfaceCreated回调之后,MediaPlayer才可以与SurfaceView关联

2. 视频播放时,SurfaceView正常显示,视频暂停后画面切入后台,再切回前台,SurfaceView区域黑屏

画面切入后台,SurfaceView销毁(surfaceDestroyed),移入前台时,SurfaceView新建(surfaceCreated),SurfaceView新建时会先将背景绘制成黑色,由于MediaPlayer一直处于暂停状态,没有状态更新,SurfaceView背景保持黑色,解决方法:画面切入后台时,记录当前播放进度,画面再次切入前台时,SurfaceView新建后,MediaPlayer调用seekTo至记录的进度

3. 视频播放时,SurfaceView正常显示,画面切入后台,视频有声音,再切回前台,播放进度无法保存

画面切入后台时,SurfaceView销毁,此时mediaPlayer仍处于播放状态,再切回前台,视频继续播放,解决方法:画面切入后台时,记录当前的播放时间并且暂停播放,画面切回前台后,当SurfaceView新建后,调用MediaPlayer的start接口继续播放

知识点

MediaPlayer工作流程

首先创建MediaPlaer对象new MediaPlayer()或者MediaPlayer.create(this, R.raw.test)指定播放文件

然后调用setDataSource()方法来设置音视频频文件的路径(如果调用MediaPlayer.create,则该步骤不需要)

再调用prepare()方法使MediaPlayer进入到准备状态(如果调用MediaPlayer.create,则该步骤不需要)

调用start方法就可以播放音频

MediaPlayer状态机

fe1025d10a73cc7eb9a3cc4aba97624d.gif

SurfaceView工作原理

SurfaceView创建一个置于应用窗口之后的新窗口,好像在视图层次(View Hierarchy)上穿了个"洞",让绘图层(Surface)直接显示出来,SurfaceView窗口刷新时不需要重绘应用程序的窗口,所以这种方式的效率非常高。但是SurfaceView也有一些非常不便的限制,因SurfaceView的内容不在应用窗口上,所以不能使用平移、缩放、旋转等变换操作,也难以放在ListView或者ScrollView中,同样不能使用UI控件的一些特性,比如View.setAlpha()

SurfaceView的双缓冲机制

SurfaceView在更新视图时用了两张Canvas,一张frontCanvas和一张backCanvas,每次显示的是frontCanvas,backCanvas存储的是上一次更改前的视图,当使用lockCanvas()获取画布时,得到的是backCanvas而不是正在显示的frontCanvas,之后在获取到的backCanvas上绘制新视图,再unlockCanvasAndPost(canvas)此视图,那么上传的这张canvas将替换原来的frontCanvas作为新的frontCanvas,原来的frontCanvas将切换到后台作为backCanvas。例如,如果你已经先后两次绘制了视图A和B,那么你再调用lockCanvas()获取视图,获得的将是A而不是正在显示的B,之后你讲重绘的C视图上传,那么C将取代B作为新的frontCanvas显示在SurfaceView上,原来的B则转换为backCanvas。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值