CameraX 一:拍照、预览

Android 专栏收录该内容
28 篇文章 0 订阅

什么是CameraX?

CameraX是一个基于camera2的加强库,具有生命周期感知能力,有很多的自感知能力,比如我们不需要处理拍照旋转,它向后兼容至21.

有没有必要升级到CameraX?

现在,你只需要两行代码就能实现与预安装的相机相同的体验和功能(what)

有生命周期感知能力

更简单的使用方式

自动解决设备的兼容性问题,减少代码量,比如自动确定可使用的最佳分辨率。包括其他宽高比、屏幕方向、旋转角度、预览大小,这些都交给CameraX

反正有意思的东西我就必须要学。。

我的计划大概是分为

预览与拍照(测试机Android 11)

CameraX是一个jatpack支持库,使用它我们需要导入依赖。

 // CameraX core library using the camera2 implementation
    def camerax_version = "1.0.0"
    // The following line is optional, as the core library is included indirectly by camera-camera2
    implementation("androidx.camera:camera-core:${camerax_version}")
    implementation("androidx.camera:camera-camera2:${camerax_version}")
    // If you want to additionally use the CameraX Lifecycle library
    implementation("androidx.camera:camera-lifecycle:${camerax_version}")
    // If you want to additionally use the CameraX View class
    implementation("androidx.camera:camera-view:1.0.0-alpha25")
    // If you want to additionally use the CameraX Extensions library
    implementation("androidx.camera:camera-extensions:1.0.0-alpha25")

记得处理CAMERA权限。

    <Button
        android:id="@+id/takeP"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="拍照" />

    <androidx.camera.view.PreviewView
        android:id="@+id/previewView"
        android:layout_width="match_parent"
        android:layout_height="0dp"
        android:layout_weight="1" />

    <ImageView
        android:layout_width="match_parent"
        android:id="@+id/imageView"
        android:layout_height="0dp"
        android:layout_weight="1" />

我们准备了三个按钮,拍照、预览、显示拍照后图片,大概这样:

获取ProcessCameraProvider,它的作用是将相机的生命周期绑定到应用程序,它是一个单例类。

 private fun initCamera() {
        cameraProviderFuture = ProcessCameraProvider.getInstance(this)
        //请求 CameraProvider 后,请验证它能否在视图创建后成功初始化。以下代码展示了如何执行此操作:
        cameraProviderFuture.addListener(Runnable {
            val cameraProvider = cameraProviderFuture.get()
            bindPreview(cameraProvider)
        }, ContextCompat.getMainExecutor(this))
    }

获取camera

     fun bindPreview(cameraProvider: ProcessCameraProvider) {
        var preview: Preview = Preview.Builder()
            .setTargetResolution(Size(1280, 720)) //设置分辨率
            .build()

//        拍照
        imageCapture = ImageCapture.Builder()
            .setCaptureMode(CAPTURE_MODE_MAXIMIZE_QUALITY) //优先考虑图片质量,速度略低
//            .setTargetRotation(Surface.ROTATION_90)
            .build()

        var cameraSelector: CameraSelector = CameraSelector.Builder()
            .requireLensFacing(CameraSelector.LENS_FACING_BACK) //后置
            .build()

        //提供previewView预览控件
        preview.setSurfaceProvider(previewView.surfaceProvider)

        var camera = cameraProvider.bindToLifecycle(
            this as LifecycleOwner,
            cameraSelector,
            imageCapture,
            preview
        )
    }

现在运行,你将看到可以正常显示预览界面,如果没有显示,请检查是否处理危险权限CAMERA。

添加拍照的点击事件

 private fun takePicture() {
        val file = File(getExternalFilesDir(Environment.DIRECTORY_PICTURES)!!.path, "1.jpg")
       
        Log.d(TAG, "initView: 拍照")
        val options = ImageCapture.OutputFileOptions.Builder(file).build()

        imageCapture?.takePicture(options, mainExecutor,
            object : ImageCapture.OnImageSavedCallback {
                override fun onError(error: ImageCaptureException) {
                    // insert your code here.
                    Log.d(TAG, "onError: " + error.message)
                }

                override fun onImageSaved(outputFileResults: ImageCapture.OutputFileResults) {
                    // insert your code here.
                    Log.d(TAG, "onImageSaved: ")
                    val savedUri = outputFileResults.savedUri ?: Uri.fromFile(file)
                    imageView.setImageURI(null)
                    imageView.setImageURI(savedUri)
                }
            })
    }

这里我使用了外部存储目录,保存在storage/emulated/0/android/data/packageName/下,如果你要保存在公共区域,可修改如下代码,或者你将直接处理图片数据,ImageCapture.OutputFileOptions.Builder的构造函数的参数,注意修改。

 ContentValues contentValues = new ContentValues();
 contentValues.put(MediaStore.MediaColumns.DISPLAY_NAME, "NEW_IMAGE");
 contentValues.put(MediaStore.MediaColumns.MIME_TYPE, "image/jpeg");
 ImageCapture.OutputFileOptions options = new ImageCapture.OutputFileOptions.Builder(
         getContentResolver(),
         MediaStore.Images.Media.EXTERNAL_CONTENT_URI,
         contentValues).build();

现在点击按钮,拍照的图片将显示在ImageView上,我们没有处理旋转角度,预览角度,CameraX帮我们自动处理了这些。

在这里插入图片描述

下一篇我们使用CameraX自带的VideoCapture实现自带的录制视频功能。

  • 0
    点赞
  • 9
    评论
  • 3
    收藏
  • 打赏
    打赏
  • 扫一扫,分享海报

评论 9 您还未登录,请先 登录 后发表或查看评论
©️2022 CSDN 皮肤主题:编程工作室 设计师:CSDN官方博客 返回首页

打赏作者

duo_shine

你的鼓励将是我创作的最大动力

¥2 ¥4 ¥6 ¥10 ¥20
输入1-500的整数
余额支付 (余额:-- )
扫码支付
扫码支付:¥2
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值