随着 CameraX API 向稳定版本迈进,您的体验和反馈对我们来说比以往任何时候都更重要!请填写这份简短的调查问卷,告诉我们该如何改进该 API。

Extensions API

CameraX 提供了一个 Extensions API,用于使用制造商在各种 Android 设备(手机、平板电脑等)上实现的特效

  • 自动:根据周围场景自动调整最终图片。例如,供应商库实现可能会执行弱光检测,并且可以切换到弱光模式或 HDR 模式以拍摄照片,库 (https://cider.corp.google.com/?ws=gfan/CS-vendor-extensions-2021-12-16_094503&sid=KmQ8x2tGPmj5Pg9kGBdU2f8WA3U#) 也可能会在拍摄肖像照时自动应用脸部照片修复模式。自动模式会根据供应商库实现选择模式。
  • 焦外成像:焦外成像模式会使前景人物看起来更加清晰,并对照片背景进行模糊处理。它通常用于拍摄与大镜头相机所生成的照片类似的人物肖像。
  • 脸部照片修复:拍摄静态图片时修复脸部肤色、几何图形等。
  • HDR(高动态范围):HDR 模式会拍摄可在最终图片中呈现较大场景亮度范围的照片。例如,在明亮窗户前拍摄某个物体的照片时,使用 HDR 模式可让该物体和窗外的场景都处于可见状态,而在正常模式下,则无法让这两者都呈现良好的曝光效果。但代价是,HDR 模式通常需要更长的时间来拍摄单张图片,用户无法控制,并且可能还需要其他工件,具体取决于所使用的 HDR 方法。
  • 夜间:在光线较暗的情况下(通常是在夜间)拍摄最佳的静态图片。

为了支持这些供应商扩展,设备必须满足以下要求:

  • 设备 ROM 为相应效果提供库支持。
  • 当前设备上已安装了 ROM 库。
  • 设备上搭载了库所要求的操作系统版本。

您可以根据以下优先原则启用扩展:如果扩展受设备支持且实际存在于设备上,则启用该扩展,否则扩展将以适当方式降级。

供应商不需要实现所有效果和功能。供应商未实现的功能都将默认采用 CameraX 实现。默认实现会报告相应功能不可用并跳过启用操作。

扩展架构

下图显示了 CameraX 的扩展架构。

图 1:CameraX 扩展架构

扩展与 CameraX 的 Camera2 核心是分开的。如图所示,红色箭头表示用户触发基于扩展的功能(例如 HDR 图片拍摄)时产生的主要数据流。

启用效果以用于图片拍摄和预览

在使用扩展 API 之前,请使用 ExtensionsManager#getInstanceAsync(Context, CameraProvider) 方法检索 ExtensionsManager 实例。这样,您就可以查询扩展可用性信息。然后检索已启用扩展的 CameraSelector。如在启用 CameraSelector 扩展的情况下调用 bindToLifecycle() 方法,则扩展模式将应用于图片拍摄和预览用例。

如需实现图片拍摄和预览用例的扩展,请参阅以下代码示例:

Kotlin

import androidx.camera.extensions.ExtensionMode
import androidx.camera.extensions.ExtensionsManager

fun onCreate() {
    // Create a camera provider
    val cameraProvider : ProcessCameraProvider = ... // Get the provider instance

    lifecycleScope.launch {
        // Create an extensions manager
        val extensionsManager =
                ExtensionsManager.getInstanceAsync(context, cameraProvider).await()

        // Select the camera
        val cameraSelector = CameraSelector.DEFAULT_BACK_CAMERA

        // Query if extension is available.
        if (extensionsManager.isExtensionAvailable(
                cameraSelector,
                ExtensionMode.BOKEH
            )
        ) {
            // Unbind all use cases before enabling different extension modes.
            cameraProvider.unbindAll()

            // Retrieve extension enabled camera selector
            val bokehCameraSelector = extensionsManager.getExtensionEnabledCameraSelector(
                cameraSelector,
                ExtensionMode.BOKEH
            )

            // Bind image capture and preview use cases with the extension enabled camera selector.
            val imageCapture = ImageCapture.Builder().build()
            val preview = Preview.Builder().build()
            cameraProvider.bindToLifecycle(
                lifecycleOwner,
                bokehCameraSelector,
                imageCapture,
                preview
            )
        }
    }
}

Java

import androidx.camera.extensions.ExtensionMode;
import androidx.camera.extensions.ExtensionsManager;

void onCreate() {
    // Create a camera provider
    ProcessCameraProvider cameraProvider = ... // Get the provider instance

    // Call the getInstanceAsync function to retrieve a ListenableFuture object
    ListenableFuture future =
            ExtensionsManager.getInstanceAsync(context, cameraProvider);

    // Obtain the ExtensionsManager instance from the returned ListenableFuture object
    future.addListener(() -> {
        try {
            ExtensionsManager extensionsManager = future.get();

            // Select the camera
            CameraSelector cameraSelector = CameraSelector.DEFAULT_BACK_CAMERA;

            // Query if extension is available.
            if (extensionsManager.isExtensionAvailable(cameraSelector, ExtensionMode.BOKEH)) {
                // Unbind all use cases before enabling different extension modes.
                cameraProvider.unbindAll();

                // Retrieve extension enabled camera selector
                CameraSelector bokehCameraSelector = extensionsManager
                    .getExtensionEnabledCameraSelector(cameraSelector, ExtensionMode.BOKEH);

                // Bind image capture and preview use cases with the extension enabled camera selector.
                ImageCapture imageCapture = new ImageCapture.Builder().build();
                Preview preview = new Preview.Builder().build();
                cameraProvider.bindToLifecycle(lifecycleOwner, bokehCameraSelector, imageCapture, preview);
            }
        } catch (ExecutionException | InterruptedException e) {
            // This should not happen unless the future is cancelled or the thread is interrupted by
            // applications.
        }
    }, ContextCompact.getMainExecutor(context));
}

停用效果

如需停用供应商扩展,请取消绑定所有用例,然后使用常规相机选择器重新绑定图片拍摄和预览用例。例如,使用 CameraSelector.DEFAULT_BACK_CAMERA 重新绑定到后置摄像头。

依赖项

CameraX Extensions API 是在 camera-extensions 库中实现的。这些扩展依赖于 CameraX 核心模块(corecamera2lifecycle)。

Groovy

dependencies {
  def camerax_version = "1.1.0-alpha08"
  implementation "androidx.camera:camera-core:${camerax_version}"
  implementation "androidx.camera:camera-camera2:${camerax_version}"
  implementation "androidx.camera:camera-lifecycle:${camerax_version}"
  //the CameraX Extensions library
  implementation "androidx.camera:camera-extensions:1.0.0-alpha28"
    ...
}

Kotlin

dependencies {
  val camerax_version = "1.1.0-alpha08"
  implementation("androidx.camera:camera-core:${camerax_version}")
  implementation("androidx.camera:camera-camera2:${camerax_version}")
  implementation("androidx.camera:camera-lifecycle:${camerax_version}")
  // the CameraX Extensions library
  implementation("androidx.camera:camera-extensions:1.0.0-alpha28")
    ...
}

移除旧版 API

1.0.0-alpha26 中发布了新版 Extensions API 后,2019 年 8 月发布的旧版 Extensions API 现已废弃。从版本 1.0.0-alpha28 开始,旧版 Extensions API 已从库中移除。现在,使用新版 Extensions API 的应用必须获取已启用扩展的 CameraSelector,并使用其绑定用例。

使用旧版 Extensions API 的应用应改用新版 Extensions API,以确保日后能与即将推出的 CameraX 版本兼容。

其他资源

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

Codelab

  • CameraX 使用入门
  • 代码示例

  • 官方 CameraX 示例应用