音视频开发系列——全面了解Android Surfaceview
Posted 伯努力不努力
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了音视频开发系列——全面了解Android Surfaceview相关的知识,希望对你有一定的参考价值。
SurfaceView和普通的View有什么区别?
SurfaceView和普通的View在实现原理和使用场景上有较大的区别。
更多音视频知识请关注公众号:进击的代码家
实现原理
SurfaceView实际上是一个包含了Surface的View,它可以在非UI线程中单独进行绘制操作,而且可以获得更高的绘制效率。而普通的View则是在UI线程中进行绘制操作的,因此如果绘制过程过于复杂,会导致UI卡顿的情况出现。
使用场景
普通的View适用于静态的UI展示,例如TextView、Button等控件。而SurfaceView则适用于需要实时绘制的场景,例如视频播放、游戏开发等。由于SurfaceView可以获得更高的绘制效率,因此在实现这些应用时,使用SurfaceView可以提供更好的用户体验。
SurfaceView的特点:
1)可以在非UI线程中进行绘制操作,避免占用主线程资源导致UI卡顿;
2)支持直接操作底层的Surface对象,能够实现更加复杂和高效的绘制操作;
3)支持透明背景,可以实现更加丰富的UI效果;
4)支持双缓冲机制,可以避免画面闪烁和撕裂的现象。
需要注意的是,由于SurfaceView的绘制操作是在子线程中进行的,因此在进行UI交互操作时需要使用Handler或其他线程通信方式来进行跨线程通信。
SurfaceView Api介绍
1.SurfaceHolder
SurfaceHolder是SurfaceView的内部类,它可以获取到SurfaceView的Surface对象,提供了对Surface的操作方法。一般在SurfaceView的回调函数中使用。
1.1 getHolder()方法
获取SurfaceHolder对象。
SurfaceHolder holder = surfaceView.getHolder();
1.2 addCallback()方法
注册SurfaceHolder.Callback回调函数。
holder.addCallback(callback);
1.3 setFixedSize()方法
设置Surface的大小。
holder.setFixedSize(width, height);
2.SurfaceHolder.Callback
SurfaceHolder.Callback是一个回调函数接口,提供了SurfaceView的生命周期回调方法。
2.1 surfaceCreated()方法
当Surface被创建时调用。
@Override
public void surfaceCreated(SurfaceHolder holder)
// 初始化MediaPlayer等对象
2.2 surfaceChanged()方法
当Surface的大小或格式改变时调用。
@Override
public void surfaceChanged(SurfaceHolder holder, int format, int width, int height)
// 更新MediaPlayer等对象的参数
2.3 surfaceDestroyed()方法
当Surface被销毁时调用。
@Override
public void surfaceDestroyed(SurfaceHolder holder)
// 释放MediaPlayer等对象
3.Canvas
Canvas是用于绘制SurfaceView的对象,可以在SurfaceHolder.Callback回调函数中使用。
3.1 lockCanvas()方法
获取Canvas对象,开始绘制操作。
Canvas canvas = holder.lockCanvas();
3.2 drawXXX()方法
进行绘制操作,例如绘制文字、图形等。
canvas.drawText("Hello, world!", x, y, paint);
3.3 unlockCanvasAndPost()方法
结束绘制操作,提交绘制结果。
holder.unlockCanvasAndPost(canvas);
4.Surface
Surface是SurfaceView内部的一个底层对象,可以直接操作Surface进行绘制操作。
4.1 getSurface()方法
获取Surface对象。
Surface surface = holder.getSurface();
4.2 setFormat()方法
设置Surface的像素格式。
surface.setFormat(PixelFormat.RGBA_8888);
4.3 setFixedSize()方法
设置Surface的大小。
surface.setFixedSize(width, height);
5.SetZOrderXXX
setZOrderOnTop和setZOrderMediaOverlay方法可以用于设置SurfaceView的Z-order,控制SurfaceView在其他View上的显示顺序。
setZOrderOnTop方法会使得SurfaceView在Z-order的最顶端显示,可以覆盖其他View,通常用于实现视频弹幕等效果;而setZOrderMediaOverlay方法会将SurfaceView显示在普通View之上,但在其他SurfaceView之下,通常用于实现UI控件和视频播放器的叠加。
这两个方法都需要传入一个布尔值参数,表示是否开启相应的Z-order,true表示开启,false表示关闭。例如:
surfaceView.setZOrderOnTop(true);
注意,这两个方法必须在SurfaceView创建之后调用,否则将无效。同时,在设置Z-order之后,可能需要更新SurfaceView的尺寸或者重绘View,以确保SurfaceView能够正确地覆盖在其他View上方或者下方。
需要注意的是,由于SurfaceView的特殊性,使用setZOrderOnTop或者setZOrderMediaOverlay方法会增加View的复杂度,可能会导致性能问题或者出现一些不可预知的问题,因此建议谨慎使用,并在具体场景下进行测试和优化。
总之,**SurfaceView的API使用相对较为简单,但需要注意在子线程中进行绘制操作,需要使用线程通信方式与UI线程进行交互。**同时,需要根据不同的应用场景进行参数的设置和优化,以提供更好的用户体验。
SurfaceView视频播放代码
public class VideoSurfaceView extends SurfaceView implements SurfaceHolder.Callback, MediaPlayer.OnPreparedListener, MediaPlayer.OnVideoSizeChangedListener
private SurfaceHolder mHolder;
private MediaPlayer mMediaPlayer;
public VideoSurfaceView(Context context)
super(context);
initView();
public VideoSurfaceView(Context context, AttributeSet attrs)
super(context, attrs);
initView();
public VideoSurfaceView(Context context, AttributeSet attrs, int defStyleAttr)
super(context, attrs, defStyleAttr);
initView();
private void initView()
mHolder = getHolder();
mHolder.addCallback(this);
@Override
public void surfaceCreated(SurfaceHolder holder)
try
mMediaPlayer = new MediaPlayer();
mMediaPlayer.setDataSource("http://example.com/video.mp4");
mMediaPlayer.setDisplay(mHolder);
mMediaPlayer.setOnPreparedListener(this);
mMediaPlayer.setOnVideoSizeChangedListener(this);
mMediaPlayer.prepareAsync();
catch (IOException e)
e.printStackTrace();
@Override
public void surfaceChanged(SurfaceHolder holder, int format, int width, int height)
@Override
public void surfaceDestroyed(SurfaceHolder holder)
mMediaPlayer.stop();
mMediaPlayer.release();
@Override
public void onPrepared(MediaPlayer mp)
mp.start();
@Override
public void onVideoSizeChanged(MediaPlayer mp, int width, int height)
if (width != 0 && height != 0)
getHolder().setFixedSize(width, height);
在这个示例代码中,我们实现了SurfaceHolder.Callback、MediaPlayer.OnPreparedListener和MediaPlayer.OnVideoSizeChangedListener接口,用于监听SurfaceView的创建、销毁事件,以及视频的准备和大小变化事件。
在surfaceCreated方法中创建MediaPlayer对象,并设置数据源和显示器为SurfaceHolder,最后异步准备MediaPlayer。在onPrepared方法中开始播放视频。在surfaceDestroyed方法中停止播放器和释放资源。在onVideoSizeChanged方法中设置SurfaceView的尺寸,确保视频可以正常显示。
需要注意的是,在实际的项目中,需要对视频播放器进行更加完善的封装和处理,包括错误处理、播放控制、缓存控制等方面的处理。这里仅仅是一个简单的示例代码,不能满足实际需求。
SurfaceView在实际项目中使用场景
SurfaceView在实际开发中有很多使用场景,以下是一些常见的应用场景:
视频播放器:SurfaceView可以在一个独立的线程中绘制视频帧,可以提供更好的性能和流畅度。
相机预览:SurfaceView可以用于相机预览,可以在预览过程中进行实时的图像处理。
游戏开发:SurfaceView可以用于游戏的绘制,可以在一个独立的线程中进行游戏的逻辑处理和渲染。
自定义绘制控件:SurfaceView可以用于实现自定义的绘制控件,可以提供更加灵活的绘制方式。
网络传输:SurfaceView可以用于网络传输,可以在一个独立的线程中处理网络数据的接收和显示。
需要注意的是,由于SurfaceView是基于Surface的,所以在使用时需要注意Surface的生命周期和内存管理。如果没有正确管理Surface的生命周期和内存,可能会导致应用程序出现异常或崩溃。因此,在实际开发中需要认真考虑SurfaceView的使用场景和具体实现方式,确保应用程序的稳定性和性能。
以上是关于音视频开发系列——全面了解Android Surfaceview的主要内容,如果未能解决你的问题,请参考以下文章
音视频开发系列——全面了解Android MediaExtractor
音视频开发系列——全面了解Android Surfaceview