Android CameraX和SurfaceView的基本使用

相机预览问题

通过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 ""
    }
  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: 在使用 CameraX API 进行相机开发时,可以使用 PreviewConfig 类来设置帧率。以下是设置帧率的示例代码: ``` val previewConfig = PreviewConfig.Builder().apply { setTargetFps(30) // 设置帧率为 30 帧每秒 }.build() val preview = Preview(previewConfig) ``` 在上面的代码中,我们使用 PreviewConfig.Builder() 创建了一个预览配置对象,并使用 setTargetFps() 方法设置了帧率为 30 帧每秒。然后,我们将预览配置对象传递给 Preview 构造函数来创建预览对象。 注意,实际帧率可能会受到硬件限制和其他因素的影响,因此设置的帧率可能不是最终实际帧率。 ### 回答2: CameraX是一个用于开发Android相机应用程序的Jetpack库。要设置CameraX的帧率,可以通过修改Preview配置来实现。 首先,需要创建一个Preview用例的实例: val preview = Preview.Builder().build() 然后,可以通过设置帧率参数来修改帧率: val frameRate = Rational(30, 1) // 设置为30fps preview.setTargetFps(frameRate) 最后,将Preview用例添加到CameraX的配置中: val cameraSelector = CameraSelector.Builder().requireLensFacing(CameraSelector.LENS_FACING_BACK).build() CameraX.bindToLifecycle(this, cameraSelector, preview) 这样就成功设置了CameraX的帧率为30fps。需要注意的是,实际的帧率可能会受到设备硬件和性能的限制,不能保证始终准确达到设置的帧率。可以根据需要调整帧率值,但应在设备支持的范围内设置合理的值以确保最佳性能和用户体验。 总结起来,要设置CameraX的帧率,需要创建Preview用例的实例并设置帧率参数,然后将Preview用例添加到CameraX的配置中。 ### 回答3: Camerax是一个相机库,用于在Android设备上以编程方式控制相机的功能。要设置相机的帧率,可以使用Camerax库中提供的一些方法和参数。 首先,我们需要创建一个Preview配置对象,并指定所需的帧率。可以使用`Builder`类来创建一个新的配置对象,然后使用`setTargetFps()`方法设置帧率。例如,如果我们希望设置帧率为30fps,可以这样做: ```java PreviewConfig config = new PreviewConfig.Builder() .setTargetFps(30) .build(); ``` 接下来,我们需要使用这个配置对象创建一个Preview实例。我们可以使用Camerax库中的`Preview`类来实现这一点。创建Preview实例的代码如下: ```java Preview preview = new Preview(config); ``` 然后,我们需要将Preview实例与相机绑定。我们可以使用Camerax库中的`CameraSelector`类来选择要绑定的相机。以下是将Preview实例与后置相机绑定的代码示例: ```java CameraSelector cameraSelector = CameraSelector.DEFAULT_BACK_CAMERA; CameraX.bindToLifecycle(this, cameraSelector, preview); ``` 最后,我们需要启动相机预览。我们可以使用Preview实例的`setSurfaceProvider()`方法将预览输出连接到界面上的SurfaceView或TextureView。以下是一个示例代码: ```java preview.setSurfaceProvider(surfaceView.getSurfaceProvider()); ``` 通过这些步骤,我们就可以使用Camerax库设置相机的帧率。可以根据需要调整帧率的值,并使用其他Camerax库中提供的配置选项来进一步定制相机的功能。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值