Android CameraX学习记录(一) kotlin

CameraX 结构

  • Preview[ 预览 ]:接受用于显示预览的图面,例如 .PreviewView
  • ImageAnalysis[ 图片分析 ]:为分析(例如机器学习)提供 CPU 可访问的缓冲区。
  • ImageCapture[ 图片拍摄 ]:拍摄并保存照片。
  • VideoCapture[ 视频拍摄 ]:通过 VideoCapture 拍摄视频和音频

查看源码Preview ImageAnalysis ImageCapture VideoCapture 这几个类都继承UseCase,
他们都属于用例
,如需使用他们需要bindToLifecycle()函数在生命周期里面进行绑定

CameraX 使用的类

ProcessCameraProvider

一个单例,可用于将相机的生命周期绑定到应用程序进程中的任何生命周期所有者。一个进程中只能存在一个进程相机提供程序,并且可以使用 getInstance(Context) 检索它。重量级资源,例如打开和正在运行的相机设备,将限定为提供给 bindToLifecycle 的生命周期(生命周期所有者、相机选择器、用例…)。其他轻量级资源(如静态相机特征)可以在使用 getInstance(Contex) 首次检索此提供程序时检索和缓存,并将在进程的生存期内持续存在。这是应用程序要使用的标准提供程序。

这是应用程序要使用的标准提供程序。

相机选择器 cameraSelector

用于选择相机或返回一组筛选的相机。
DEFAULT_BACK_CAMERA 选择默认后置摄像头的静态。
DEFAULT_FRONT_CAMERA 选择默认前置摄像头的静态。
LENS_FACING_BACK = 1 设备上的摄像头,其方向与设备屏幕相反。
LENS_FACING_FRONT = 0 设备上的摄像头与设备屏幕朝向同一方向。

CameraX 使用流程

权限
绑定生命周期
创建预览
相机选择器
获取Camera对象
使用UseCase用例

权限

使用相机需要声明权限

<uses-permission android:name="android.permission.CAMERA" />
<uses-feature android:name="android.hardware.camera.any" />
<!-- 应用程序至少用到一个摄像头,无所谓其朝向,如果有连接的外置摄像头也可以。 如果不是非要使用后置摄像头的话,可优先选用本设置,而不是 android.hardware.camera。 -->

uses-feature参考:Android开发-API指南-<uses-feature>
如需将图片保存到文件中,除非所用设备搭载 Android 10 或更高版本,否则应用还需要 WRITE_EXTERNAL_STORAGE 权限。

<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
// 请求相机权限
ActivityCompat.requestPermissions(
    this, 
    arrayOf(Manifest.permission.CAMERA), 
    0x1001)
	// 监听权限
    override fun onRequestPermissionsResult(
        requestCode: Int,
        permissions: Array<out String>,
        grantResults: IntArray
    ) {
        super.onRequestPermissionsResult(requestCode, permissions, grantResults)
        if (requestCode == 0x1001){
            if (permissions.contains(
            Manifest.permission.CAMERA) && grantResults.get(0) == 0){
                startCamera()
            }
        }
    }

添加依赖

将以下内容添加到app目录下的 build.gradle 文件中:

dependencies {
    // CameraX core library using the camera2 implementation
    def camerax_version = "1.3.0-alpha02"
    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 VideoCapture library
    implementation("androidx.camera:camera-video:${camerax_version}")
    // If you want to additionally use the CameraX View class
    implementation("androidx.camera:camera-view:${camerax_version}")
}

布局

编写activity_main

<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".MainActivity">

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

</androidx.constraintlayout.widget.ConstraintLayout>

生命周期

CameraX 没有在onResume()onPause()中放置具体的启动和停止方法调用,而是使用cameraProvider.bindToLifecycle()指定要与相机关联的生命周期。之后,该生命周期会告知 CameraX 何时配置相机拍摄会话并确保相机状态随生命周期的转换相应地变化。

请求 CameraProvider

private lateinit var cameraProviderFuture : ListenableFuture<ProcessCameraProvider>
cameraProviderFuture = ProcessCameraProvider.getInstance(this)

检查 CameraProvider 可用性

请求 CameraProvider 后,请验证它能否在视图创建后成功初始化。以下代码展示了如何执行此操作:

cameraProviderFuture.addListener(Runnable {
    val cameraProvider = cameraProviderFuture.get()
    bindPreview(cameraProvider)
}, ContextCompat.getMainExecutor(this))

预览

// 预览
val preview = Preview.Builder().build()
// 使用以下代码将用例绑定到Android生命周期 
val camera = cameraProvider.bindToLifecycle(this as LifecycleOwner, cameraSelector, preview)
// PreviewView创建一个表面提供程序,并且是推荐的提供程序
camera = preview.setSurfaceProvider(previewView.getSurfaceProvider())

bindToLifecycle() 会返回一个 Camera 对象。

bindToLifecycle()函数

查看bindToLifecycle()函数源码可以得知

public Camera bindToLifecycle(LifecycleOwner lifecycleOwner,
            CameraSelector cameraSelector,
            UseCase... useCases)

lifecycleOwner:生命周期所有者,用于控制用例的生命周期转换。
cameraSelector:相机选择器,用于确定用于一组用例的相机。
useCases:要绑定到生命周期的用例。
Preview[ 预览 ]Image analysis[ 图片分析 ]Image capture[ 图片拍摄 ]Video capture[ 视频拍摄 ]

查看源码可知他们父类都是UseCase,因此要使用哪个用例需要绑定到生命周期

预览完整代码

private fun startCamera(){
        // 将相机的生命周期绑定到应用程序进程中  "getInstance"一个进程中只能存在一个进程相机提供程序,可以使用 进行检索。
        val cameraProviderFuture = ProcessCameraProvider.getInstance(this)
        bindPreview(cameraProviderFuture)
    }

// 用于将相机的生命周期绑定到生命周期所有者
private fun bindPreview(cameraProviderFuture: ListenableFuture<ProcessCameraProvider>){
    cameraProviderFuture.addListener(Runnable {
	    val cameraProvider: ProcessCameraProvider = cameraProviderFuture.get()
	    // 创建预览 Preview
	    val preview = Preview.Builder()
	        .build()
	        .also {
	            it.setSurfaceProvider(previewView.surfaceProvider)
	        }
	    // 选择后置摄像头作为默认值
	    val cameraSelector = CameraSelector.DEFAULT_BACK_CAMERA
	    try {
	        // 在重新绑定之前取消绑定用例Unbind use cases before rebinding
	        cameraProvider.unbindAll()
	        // 将用例绑定到相机 Bind use cases to camera
	        camera = cameraProvider.bindToLifecycle(
	            this, cameraSelector, preview)
	    } catch(exc: Exception) {
	        Log.e(TAG, "Use case binding failed", exc)
	    }
	},
	    // 返回一个将在与此上下文关联的主线程上运行排队任务
	    ContextCompat.getMainExecutor(this)
	)
}

参考资料:
CameraX 入门指南
CameraX 概览

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值