Android CameraX和SurfaceView的基本使用_camerax surfaceview-程序员宅基地

技术标签: android  PreviewView  cameraX  Android  

相机预览问题

通过SurfaceView,TextureView,GlSurfaceView显示相机预览

显示相机预览内容是每个相机类应用都会包含的功能,想要完美实现这个却并非易事。原因是,在某些特别极端情况下 camera2 API 的使用会变得很复杂,而且在不同设备上的行为还会有所不同。还好, Jetpack CameraX 库 的 PreviewView 可以帮助您解决这一问题。通过在各种 Android 设备上提供开发者友好、一致且稳定的 API,使得展示相机的预览变得不再困难。

如果要向 Android 应用中添加相机功能,您有以下三个主要选项:

CameraX 基于 Camera2 软件包构建而成。如果您需要低级别的相机控件来支持复杂用例,那么 Camera2 是一个不错的选择,但相应 API 比 CameraX 更复杂,并且您需要管理设备专属配置。与 CameraX 一样,Camera2 适用于 Android 5.0(API 级别 21)及更高版本。

CameraX 支持大多数常见的相机用例:

  • 预览:在屏幕上查看图片。
  • 图片分析:无缝访问缓冲区中的图片以便在算法中使用,例如将其传递到机器学习套件。
  • 图片拍摄:保存图片。
  • 视频拍摄:保存视频和音频。

使用SurfaceView加载相机预览界面

1,添加相机权限

   <uses-permission android:name="android.permission.CAMERA" />

2,页面布局,因为我项目需要的是一个扫描页面,所以我在底布局下填充了一个SurfaceView

    <SurfaceView
        android:id="@+id/mSurfaceView"
        android:layout_width="match_parent"
        android:layout_height="match_parent" />

    <ImageView
        android:id="@+id/view2"
        android:layout_width="0dp"
        android:layout_height="0dp"
        android:layout_margin="60dp"
        android:background="@drawable/rpa_huli_rzpz_bianjiao_icon"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintDimensionRatio="h,16:10"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintRight_toRightOf="parent"
        app:layout_constraintTop_toTopOf="parent" />

    <Button
        android:id="@+id/face_confirm"
        android:layout_width="@dimen/public_120_dp"
        android:layout_height="@dimen/public_60_dp"
        android:layout_marginTop="136dp"
        android:background="@color/detail_bu"
        android:text="识别"
        android:textColor="@color/white"
        android:textSize="24sp"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintRight_toRightOf="parent"
        app:layout_constraintTop_toBottomOf="@+id/view2" />

3,设置SurfaceHolder.callback开启和关闭相机预览功能。

    private val cpHolderCallback: SurfaceHolder.Callback = object : SurfaceHolder.Callback {
    
        override fun surfaceCreated(holder: SurfaceHolder) {
    
            camera?.setPreviewDisplay(holder)
            preview()//相机预览
        }
        override fun surfaceChanged(holder: SurfaceHolder, format: Int, width: Int, height: Int)       {
    }
        override fun surfaceDestroyed(holder: SurfaceHolder) {
    
            stopPreview()//关闭预览
        }
    }

4,初始化相机数据,加载相机预览

  runOnUiThread {
    
            camera = Camera.open(0)
            try {
    
                val parameters: Camera.Parameters = camera!!.parameters
                parameters.pictureFormat = ImageFormat.JPEG//设置图片属性
                //设置相机对焦模式,FOCUS_MODE_CONTINUOUS_PICTURE使用连续对焦
                parameters.focusMode = Camera.Parameters.FOCUS_MODE_CONTINUOUS_PICTURE
                //界面属性不一样,所以设置宽高处理界面异常拉伸
                val display = windowManager.defaultDisplay
                val height = display.height
                val width = display.width
                val preSize: Camera.Size =
                    CameraUtils.getCloselyPreSize(true, width,height,
                        parameters.supportedPreviewSizes)
                parameters.setPictureSize(preSize.width, preSize.height)
                camera!!.run {
    
                    setParameters(parameters)
                    setPreviewDisplay(mSurfaceView.holder)
                    //设置将相机获取到的界面旋转90度显示
                    setDisplayOrientation(90)
                    startPreview()
                    cancelAutoFocus()
                }
                safeToTakePicture = true
            } catch (e: IOException) {
    
                e.printStackTrace()
            }
        }

5,监听扫描按钮,获取到图片,这里因为是预览界面,所以和平时相机拍照的方法有一些区别,需要使用takePicture函数,三个参数我使用了图片回调,因为我需要得到图片。

 face_confirm.setOnClickListener {
    
     camera?.takePicture(null, null, Camera.PictureCallback {
     data, _ ->
                    //data是ByteArray类型的,所以需要转换一下才能得到图片临时存放的地址
                    pictureDataBytes = data
                    stopPreview()//获取完之后停止相机预览活动
              ...
                    }).start()
                })
 }

6,ByteArray转换String函数,获取到图片的拼接地址。

   private fun PictureConversion(bytes: ByteArray?): String? {
    
        try {
    
            val f: File = File.createTempFile("img", ".jpg")
            val fos = FileOutputStream(f)
            fos.write(bytes)
            fos.flush()
            fos.close()
            return f.getAbsolutePath()
        } catch (e: IOException) {
    
            e.printStackTrace()
        }
        return ""
    }
版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/weixin_44008788/article/details/126491579

智能推荐

如何在DOS命令窗口从C盘进入D盘?_dos怎么从c盘到d盘-程序员宅基地

文章浏览阅读3.6k次。点击开始,打开运行输入cmd,进入DOS窗口输入D:即可进入D盘_dos怎么从c盘到d盘

思岚激光雷达+cartographer建图_思岚a1与cartographer-程序员宅基地

文章浏览阅读4.3k次,点赞6次,收藏71次。思岚+cartographer_思岚a1与cartographer

开源埋点工具分析比较_开源埋点系统-程序员宅基地

文章浏览阅读1w次。开源埋点工具分析查找和比较_开源埋点系统

vite+vue3 2-程序员宅基地

文章浏览阅读63次。答:选择To check syntax, find problems, and enforce code style(检查语法、发现问题并强制执行代码风格)1.在vue3中,规则vue/name-property--casing已经被vue/component-definition-name-casing代替,在使用前者会出错。a).安装postcss和postcss-preset-env插件:npm install postcss postcss-preset-env -D。(你想遵循哪一种风格指南?

使用IDM下载百度云盘文件提示“此站点/路径要求授权”解决方法_idm此站点路径要求授权-程序员宅基地

文章浏览阅读1.4w次,点赞6次,收藏11次。使用IDM下载百度云盘文件提示“此站点/路径要求授权”解决方法问题描述解决方法问题描述利用IDM下载百度云盘文件时,未下载完成时提示“此站点/路径要求授权”,要求输入账户和密码,然而输入啥都没用。解决方法停止下载,右键下载项目——属性,可以发现下载的URL改变了。所以要把URL改回来。在浏览器再次下载文件,IDM会弹出“下载文件信息”将图中的URL信息放到之前下载项目右键——属性的..._idm此站点路径要求授权

idea新版UI的TODO工具栏位置_idea将todo添加到侧边栏-程序员宅基地

文章浏览阅读595次,点赞7次,收藏6次。_idea将todo添加到侧边栏

随便推点

爽文被搬上小程序短剧,用十万成本撬动千万生意-程序员宅基地

文章浏览阅读1.1k次,点赞36次,收藏16次。和传统长视频相比,小程序短剧不注水,在最短的时间内,完成更多的戏剧矛盾冲突和反转,也更容易抓住观众的好奇心。小程序短剧的主打就是短、快、剧情爽,人们对于视频内容要求的情绪价值,小程序短剧能很好的贴合需求。通过以上商业盈利模式,短剧小程序可以实现多方面的收入来源,包括广告收入、付费会员收入和虚拟商品销售收入,从而为开发者带来可观的经济效益。如果不想组建小程序开发团队,想定制化开发小程序,有个性化功能需要满足,建议采取外包开发的方式,选择专业的开发服务商,列出自己的开发需求,交给专业的团队去开发维护。

数据结构笔记(5)树的基础介绍_三叉树-程序员宅基地

文章浏览阅读1k次。前言接下来就是数据结构的第二大板块:树之前的第一板块:线性表中的顺序表和链表已经更完。但由于队列和栈是特殊的线性表,既然特殊,实际上就普通的顺序表和链表也能实现,加上队列和栈可直接STL实现。故由此,先暂时跳过队列和栈的实现(实际上队列和栈的实现也是仿STL的)笔记(1)为顺序表仿STL的实现,笔记(2)为链表的实现,笔记(3)为队列的仿STL实现,笔记(4)为栈的仿STL实现,而本篇笔记(5)则介绍树形结构树的定义树是一种数据结构,它是由n(n≥0)个有限节点组成一个具有层次关系_三叉树

《转载》struts旅程《1》-程序员宅基地

文章浏览阅读54次。struts简介Struts是Apache软件基金会(ASF)赞助的一个开源项目。它最初是jakarta项目中的一个子项目,并在2004年3月成为ASF的顶级项目。它通过采用JavaServlet/JSP技术,实现了基于JavaEEWeb应用的MVC设计模式的应用框架,是MVC经典设计模式中的一个经典产品。Struts发展历史Struts是作为ApacheJakarta项目的组成部分,...

javaweb分页查询实现-程序员宅基地

文章浏览阅读391次。Javaweb分页技术实现分页技术就是通过SQL语句(如下)来获取数据,具体实现看下面代码//分页查询语句select * from 表名 where limit page , count;和//获取表中的总数据,确定页数select count(*) from 表名;不说废话直接上代码前端代码:<!DOCTYPE html>..._javaweb之分页查询 post请求写

linux内核 异常 log,Linux Kernel WARN()/BUG(), Oops/Panic, Tainted分析-程序员宅基地

文章浏览阅读2.7k次。稳定性范畴, 参考5.x kernel。kernel OopsOops指的就是内核的不正确行为,比如对驱动来说:static int i82092aa_pci_probe(struct pci_dev *dev,const struct pci_device_id *id){unsigned char configbyte;int i, ret;ret = pci_enable_device(de..._kernel warn

forward和redirect区别_forward 和 redirect 区别?-程序员宅基地

文章浏览阅读266次。_forward 和 redirect 区别?

推荐文章

热门文章

相关标签