CameraX 架构

CameraX 是对 Jetpack 的补充,可让您更轻松地利用 Camera2 API 的功能。本主题介绍了 CameraX 的架构,包括其结构、如何与 API 搭配使用、如何与 Lifecycle 配合以及如何组合各种用例。

CameraX 结构

开发者使用 CameraX,借助名为“用例”的抽象概念与设备的相机进行交互。目前提供的用例如下:

  • 预览:准备一个预览 SurfaceTexture
  • 图片分析:提供 CPU 可访问的缓冲区以进行分析(例如进行机器学习)
  • 图片拍摄:拍摄并保存照片

不同用例可以相互组合使用,也可以同时处于活动状态。例如,用户可以在应用中使用预览用例查看进入相机视野的画面、加入图片分析用例来确定照片里的人物是否在微笑,以及包含一个图片拍摄用例以便在人物微笑时拍摄照片。

API 模型

要使用该库,请指定以下内容:

  • 具有配置选项的所需用例
  • 通过附加监听器来指定如何处理输出数据
  • 通过将用例绑定到 Android 架构生命周期来指定目标流程,例如何时启用相机及何时生成数据

用例的配置对象使用 set() 方法配置,并使用 build() 方法最终确定。每个用例对象都提供一组特定于该用例的 API。例如,图片拍摄用例提供 takePicture() 方法调用。

应用使用 CameraX.bindToLifecycle() 指定要与相机关联的生命周期,而不是将特定的开始和结束方法调用放入 onResume()onPause()。数据的启动、关闭和生成均由指定的 Android 架构生命周期控制。之后,该生命周期会告知 CameraX 何时配置相机拍摄会话并确保相机状态随生命周期的转换相应地更改。

如需了解每个用例的实现步骤,请参阅实现预览分析图片拍摄照片

API 模型示例

预览用例提供用于显示的 SurfaceTexture。应用使用以下代码创建具有配置选项的用例:

Kotlin

    val previewConfig = PreviewConfig.Builder().build()
    val preview = Preview(previewConfig)

    val textureView: TextureView = findViewById(R.id.textureView)

    // The output data-handling is configured in a listener.
    preview.setOnPreviewOutputUpdateListener { previewOutput ->
        textureView.surfaceTexture = previewOutput.surfaceTexture
    }

    // The use case is bound to an Android Lifecycle with the following code.
    CameraX.bindToLifecycle(this as LifecycleOwner, preview)
    

Java

    PreviewConfig config = new PreviewConfig.Builder().build();
    Preview preview = new Preview(config);

    TextureView textureView = findViewById(R.id.textureView);

    preview.setOnPreviewOutputUpdateListener(
        new Preview.OnPreviewOutputUpdateListener() {
            @Override
            public void onUpdated(Preview.PreviewOutput previewOutput) {
                // The output data-handling is configured in a listener.
                textureView.setSurfaceTexture(previewOutput.getSurfaceTexture());
                // Your custom code here.
            });
    });

    // The use case is bound to an Android Lifecycle with the following code.
    CameraX.bindToLifecycle((LifecycleOwner) this, preview);
    

如需查看更多示例代码,请参阅官方 CameraX 示例应用

CameraX 生命周期

CameraX 会观察生命周期以确定何时打开相机、何时创建拍摄会话以及何时停止和关闭。用例 API 提供方法调用和回调来监控进度情况。

组合用例中所述,您可以将多个用例一起绑定到单个生命周期。当您的应用需要支持无法组合的用例时,您可以执行以下操作之一:

  • 将兼容的用例归入多个片段中,然后并在片段之间进行切换
  • 创建自定义生命周期组件并用其手动控制相机生命周期

如果您将视图用例和相机用例的生命周期所有者分离开(例如,如果您使用自定义生命周期或保留片段),则必须通过使用 CameraX.unbindAll() 或逐个取消绑定各个用例来确保所有用例均未绑定 CameraX。或者,当您在标准生命周期的 onCreate 方法中绑定用例时,可以让 CameraX 管理拍摄会话的开启和关闭操作以及用例的取消绑定操作。

如果所有相机功能都对应于单个具有生命感知能力的组件(例如 AppCompatActivityAppCompat 片段)的生命周期,则在绑定所有所需用例时使用相应组件的生命周期可确保相机功能在具有感知生命周期能力的组件处于活动状态时准备就绪且可安全处置,否则不消耗任何资源。

自定义 LifecycleOwner

对于高级用例,您可以创建自定义 LifecycleOwner 以使您的应用显式控制 CameraX 会话生命周期,而不是将其绑定到标准 Android LifecycleOwner

以下代码示例显示了如何创建简单的自定义 LifecycleOwner:

Kotlin

    class CustomLifecycle : LifecycleOwner {
        private val lifecycleRegistry: LifecycleRegistry

        init {
            lifecycleRegistry = LifecycleRegistry(this);
            lifecycleRegistry.markState(Lifecycle.State.CREATED)
        }
        ...
        fun doOnResume() {
            lifecycleRegistry.markState(State.RESUMED)
        }
        ...
        override fun getLifecycle(): Lifecycle {
            return lifecycleRegistry
        }
    }
    

Java

    public class CustomLifecycle implements LifecycleOwner {
        private LifecycleRegistry mLifecycleRegistry;
        public CustomLifecycle() {
            mLifecycleRegistry = new LifecycleRegistry(this);
            mLifecycleRegistry.markState(Lifecycle.State.CREATED);
        }
       ...
       public void doOnResume() {
            mLifecycleRegistry.markState(State.RESUMED);
        }
       ...
        public Lifecycle getLifecycle() {
            return mLifecycleRegistry;
        }
    }
    

借助此 LifecycleOwner,您的应用可以将状态转换放在代码中的所需位置。如需详细了解如何在应用中实现此功能,请参阅实现自定义 LifecycleOwner

组合用例

多个用例可以同时运行。虽然可以将用例依序绑定到生命周期,但最好通过一次调用 CameraX.bindToLifecycle() 来绑定所有用例。如需详细了解有关配置更改的最佳做法,请参阅处理配置更改

在以下代码示例中,应用指定了要创建并同时运行的两个用例,还指定了同时用于这两个用例的生命周期,以便它们根据生命周期启动和停止。

Kotlin

    val imageCapture: ImageCapture

    override fun onCreate() {
        val previewConfig = PreviewConfig.Builder().build()
        val imageCaptureConfig = ImageCaptureConfiguration.Builder().build()

        val imageCapture = ImageCapture(imageCaptureConfig)
        val preview = Preview(previewConfig)

        val textureView = findViewById(R.id.textureView)

        preview.setOnPreviewOutputUpdateListener { previewOutput ->
            textureView.surfaceTexture = previewOutput.surfaceTexture
        }

        CameraX.bindToLifecycle(this as LifecycleOwner, preview, imageCapture)
    }
    

Java

    private ImageCapture imageCapture;

    void onCreate() {
        PreviewConfig previewConfig = new PreviewConfig.Builder().build();
        imageCaptureConfig imageCaptureConfig =
            new ImageCaptureConfig.Builder().build();

        imageCapture = new ImageCapture(imageCaptureConfig);
        preview = new Preview(previewConfig);

        TextureView textureView = findViewById(R.id.textureView);

        preview.setOnPreviewOutputUpdateListener(
            previewOutput -> {
                textureView.setSurfaceTexture(previewOutput.getSurfaceTexture());
        });

        CameraX.bindToLifecycle((LifecycleOwner) this, preview, imageCapture);
    }
    

支持以下配置组合:

预览 分析 图片拍摄 组合用例
为用户提供预览、拍摄照片并分析图片流。
拍摄照片并分析图片流。
提供预览,其中根据对流式传输的图片的分析应用了视觉效果。
显示进入相机视野的画面并根据用户操作拍摄照片。

权限

您的应用需要 CAMERA 权限。要将图片保存到文件,除了所用设备要搭载 Android Q 或更高版本之外,应用还需要 WRITE_EXTERNAL_STORAGE 权限。

如需详细了解如何为应用配置权限,请参阅请求应用权限

要求

CameraX 具有以下最低版本要求:

  • Android API 级别 21
  • Android 架构组件 1.1.1

对于具有生命周期感知能力的 Activity,请使用 FragmentActivityAppCompatActivity

声明依赖项

要在 CameraX 中添加依赖项,您必须将 Google Maven 代码库添加到项目中。

打开项目的 build.gradle 文件,然后添加 google() 代码库,如下所示:

    allprojects {
      repositories {
        google()
        jcenter()
      }
    }
    

将以下内容添加到每个模块的 build.gradle 文件中:

    dependencies {
        // CameraX core library.
        def camerax_version = "1.0.0-alpha01"
        implementation "androidx.camera.core:core:$camerax_version"
        // If you want to use CameraView.
        implementation "androidx.camera.core:view:$camerax_version"
        // If you want to use Camera2 extensions.
        implementation "androidx.camera.core:camera2:$camerax_version"
    }
    

如需详细了解如何配置应用以满足上述要求,请参阅声明依赖项

其他资源

要详细了解 CameraX,请参阅下面列出的其他资源。

Codelab

  • CameraX 使用入门
  • 向应用中添加 CameraView 片段
  • 代码示例

  • 官方 CameraX 示例应用