文章详情

短信预约-IT技能 免费直播动态提醒

请输入下面的图形验证码

提交验证

短信预约提醒成功

AndroidSurfaceView与TextureView使用方法详细讲解

2022-11-13 19:07

关注

Surface

官方对Surface的解释是:由屏幕合成器管理的原始缓冲区上的句柄,所谓原生缓冲器,是用于保存当前窗口的像素数据的,也就是说,通过Surface可以获取原生缓冲器以及其中的内容。Surface对应一块屏幕缓冲区,每个Window对应一个Surface,任何View都画在Surface上,Surface中的Canvas,是用于提供画图的地方。

SurfaceView

SurfaceView与普通的View不同,它拥有自己的Surface,它的工作方式是创建一个区别于应用窗口的新窗口,与宿主窗口分离,可以在单独线程中处理业务,不受View的属性控制,无法进行平移缩放等转换,它是通过“双缓冲”机制来达到高效的界面刷新效果。

双缓冲技术是把要处理的图片在内存中处理好之后,再将其显示在屏幕上。双缓冲主要是为了解决反复局部刷屏带来的闪烁。把要画的东西先画到一个内存区域里,然后整体的一次性画出来。

下面通过一个相机预览的功能,来看一下SurfaceView的具体使用

private lateinit var surfaceHolder: SurfaceHolder

获取摄像机管理类,打开某个具体的摄像机,在打开成功的回调里面,创建预览请求

        val cameraManager = getSystemService(Context.CAMERA_SERVICE) as CameraManager
        val surfaceView = findViewById<SurfaceView>(R.id.surfaceView)
        surfaceHolder = surfaceView.holder
        surfaceHolder.setKeepScreenOn(true)
        surfaceHolder.addCallback(object : SurfaceHolder.Callback {
            override fun surfaceCreated(p0: SurfaceHolder) {
                if (ActivityCompat.checkSelfPermission(
                        this@SurfaceActivity,
                        Manifest.permission.CAMERA
                    ) != PackageManager.PERMISSION_GRANTED
                ) {
                    //无相机权限
                    return
                }
                try {
                    //获取可用相机设备列表
                    val cameraIdList = cameraManager.cameraIdList
                    //打开相机
                    cameraManager.openCamera(
                        cameraIdList[0],
                        //摄像头创建监听
                        object : CameraDevice.StateCallback() {
                            override fun onOpened(p0: CameraDevice) { //打开摄像头
                                try {
                                    startPreview(p0)
                                } catch (e: CameraAccessException) {
                                    e.printStackTrace()
                                }
                            }
                            override fun onDisconnected(p0: CameraDevice) { //关闭摄像头
                                p0.close()
                            }
                            override fun onError(p0: CameraDevice, p1: Int) {
                                Log.i(tag, "CameraDevice.StateCallback onError")
                            }
                        },
                        null
                    )
                } catch (e: CameraAccessException) {
                    e.printStackTrace()
                }
            }
            override fun surfaceChanged(p0: SurfaceHolder, p1: Int, p2: Int, p3: Int) {
                Log.i(tag, "surfaceChanged")
            }
            override fun surfaceDestroyed(p0: SurfaceHolder) {
                Log.i(tag, "surfaceDestroyed")
            }
        })

开始预览

    private fun startPreview(cameraDevice: CameraDevice) {
        val captureRequest = cameraDevice.createCaptureRequest(CameraDevice.TEMPLATE_PREVIEW)
        captureRequest.addTarget(surfaceHolder.surface)
        cameraDevice.createCaptureSession(
            listOf(surfaceHolder.surface),
            //会话状态回调
            object : CameraCaptureSession.StateCallback() {
                override fun onConfigured(p0: CameraCaptureSession) {
                    try {
                        // 创建预览需要的CaptureRequest.Builder
                        val previewRequestBuilder =
                            cameraDevice.createCaptureRequest(CameraDevice.TEMPLATE_PREVIEW)
                        previewRequestBuilder.addTarget(surfaceHolder.surface)
                        val previewRequest = previewRequestBuilder.build()
                        p0.setRepeatingRequest(previewRequest, null, null)
                    } catch (e: CameraAccessException) {
                        e.printStackTrace()
                    }
                }
                override fun onConfigureFailed(p0: CameraCaptureSession) {
                    Log.i(tag, "onConfigureFailed")
                }
            }, null
        )
    }

这样,简易的相机预览功能就出来啦,当然,我们还需要申请CAMERA权限,这里略去。

TextureView

TextureView可以说是一个结合了View和SurfaceTexture的View对象,一个可以把内容流作为外部纹理输出在上面的 View,它只能用于开启了硬件加速的窗口,TextureView不会创建一个独立的窗口,而是像普通的View一样,可以进行平移、旋转等动画,TextureView在Andriod 4.0之后的 API 中才能使用,不过现在的安卓设备基本不存在Andriod 4.0之前的版本了,所以这点不必在意。

TextureView的使用也比较简单,需要获取到它的SurfaceTexture,然后就可以以此来渲染了,下面通过一个简易的视频播放的示例,来瞧瞧它是怎么使用的。

        val textureView = findViewById<TextureView>(R.id.textureView)
        val mediaPlayer = MediaPlayer()
        textureView.surfaceTextureListener = object : TextureView.SurfaceTextureListener {
            override fun onSurfaceTextureAvailable(p0: SurfaceTexture, p1: Int, p2: Int) {
                with(mediaPlayer) {
                    setDataSource(GlobalData.videoUrl)
                    setSurface(Surface(p0))
                    prepare()
                    start()
                    Log.i(tag, "setOnPreparedListener")
                    setOnPreparedListener {
                        it.start()
                    }
                }
            }
            override fun onSurfaceTextureSizeChanged(p0: SurfaceTexture, p1: Int, p2: Int) {
            }
            override fun onSurfaceTextureDestroyed(p0: SurfaceTexture): Boolean {
                mediaPlayer.stop()
                mediaPlayer.release()
                return true
            }
            override fun onSurfaceTextureUpdated(p0: SurfaceTexture) {
            }
        }

SurfaceTexture

SurfaceTexture是Surface和OpenGL ES纹理的组合,用于提供输出到OpenGL ES纹理的Surface,和SurfaceView不同的是,它对图像流的处理并不直接显示,而是转为GL外部纹理,因此可用于图像流数据的二次处理,如Camera滤镜,桌面特效等,但是这样会有若干帧的延迟。同时,由于它本身管理BufferQueue,因此内存消耗也会稍微大一些。比如Camera的预览数据,变成纹理后就可以通过SurfaceTexture交给TextureView作为View层级中的一个硬件加速层来显示。

SurfaceView和TextureView的区别

SurfaceViewTextureView
占用内存低占用内存高
耗电低耗电高
绘制及时1-3帧延时
不支持动画截图支持动画截图

个人觉得,对于需要不断更新画布的游戏来说,SurfaceView是最好的选择,对于视频播放器或相机应用的开发,则TextureView更加适合。

到此这篇关于Android SurfaceView与TextureView使用方法详细讲解的文章就介绍到这了,更多相关Android SurfaceView与TextureView内容请搜索编程网以前的文章或继续浏览下面的相关文章希望大家以后多多支持编程网!

阅读原文内容投诉

免责声明:

① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。

② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341

软考中级精品资料免费领

  • 历年真题答案解析
  • 备考技巧名师总结
  • 高频考点精准押题
  • 2024年上半年信息系统项目管理师第二批次真题及答案解析(完整版)

    难度     801人已做
    查看
  • 【考后总结】2024年5月26日信息系统项目管理师第2批次考情分析

    难度     348人已做
    查看
  • 【考后总结】2024年5月25日信息系统项目管理师第1批次考情分析

    难度     311人已做
    查看
  • 2024年上半年软考高项第一、二批次真题考点汇总(完整版)

    难度     432人已做
    查看
  • 2024年上半年系统架构设计师考试综合知识真题

    难度     220人已做
    查看

相关文章

发现更多好内容

猜你喜欢

AI推送时光机
位置:首页-资讯-移动开发
咦!没有更多了?去看看其它编程学习网 内容吧
首页课程
资料下载
问答资讯