现代相机应用具有强大的重叠功能。用户希望能够录制出色的 HDR 视频,以 60 FPS 的帧速率拍摄流畅的运动画面,并通过预览防抖功能获得顺畅的视频片段,而且通常希望能够同时实现这些功能。
作为开发者,我们知道现实情况更加复杂。如何保证特定设备实际支持给定的组合?在过去,启用多项功能往往是一场赌博。您可以检查各个功能是否受支持,但将它们组合在一起可能会导致未定义的行为,或者更糟糕的是,导致摄像头会话失败。这种不确定性迫使开发者采取保守的做法,从而导致使用功能强大的设备的用户无法获得尽可能好的体验。
例如,很少有高端设备能够同时可靠地支持 HDR 和 60 FPS 视频。因此,大多数应用都会避免同时启用这两项功能,以免在大多数手机上造成糟糕的用户体验。
为了解决这个问题,我们推出了 CameraX 中的功能组,这是一个旨在消除这种猜测的新 API。您现在可以在配置相机之前查询是否支持特定的功能组合,也可以直接告知 CameraX 您的优先级,让它为您启用最受支持的组合。
CameraX 新手
在深入了解新的功能组 API 之前,我们先快速回顾一下 CameraX 是什么。CameraX 是一个 Jetpack 支持库,旨在帮助您简化相机应用的开发工作。它提供一致且易于使用的 API Surface,适用于大多数 Android 设备,并可向后兼容至 Android 6.0(API 级别 23)。如果您刚开始接触 CameraX,建议您查看官方文档并试用 Codelab 以开始使用。
您可以使用 Feature Group API 构建哪些内容
您不再需要冒险尝试功能组合,可以放心地提供尽可能出色的相机体验,例如在支持的硬件(例如 Pixel 10 Pro)上同时使用 HDR 和 60 FPS 视频,同时在无法支持该组合的设备上优雅地避免错误。
Pixel 10 Pro 同时启用 HDR 和 60 FPS
在无法同时运行 HDR 和 60 FPS 的旧设备上,系统只会启用 HDR,同时停用 60 FPS 选项。
借助 Feature Group API,您可以:
- 构建更智能的动态界面:根据实时硬件支持情况,在界面中智能地启用或停用设置。例如,如果用户启用了 HDR,但相应设备不支持 HDR 和 60 FPS 的组合,您可以立即将 60 FPS 选项灰显并停用。
- 提供可靠的“高画质”模式: 使用所需功能的优先级列表配置相机。CameraX 会自动查找并启用任何给定设备支持的最佳组合,从而确保获得出色的效果,而无需复杂的设备专用逻辑。
- 防止相机会话失败:通过预先验证支持情况,您可以防止相机尝试配置不受支持的组合,从而消除常见的崩溃来源,并提供流畅的用户体验。
运作方式:核心组件
新 API 的核心是 SessionConfig 和 CameraInfo 的关键新增功能。
- GroupableFeature:此 API 引入了一组预定义的可分组功能,例如 HDR_HLG10、FPS_60、PREVIEW_STABILIZATION 和 IMAGE_ULTRA_HDR。由于计算限制,只有一组特定的特征可以与此 API 提供的高可靠性进行分组。我们正在积极努力扩大此列表,并将在未来的版本中推出对更多功能的支持。
- 新的 SessionConfig 参数:用于启动相机会议的此类现在接受两个新参数:
requiredFeatureGroup:如果某项功能必须受支持才能成功完成配置,请使用此值。此值非常适合用户明确启用的功能,例如切换“HDR”开关。为确保确定性和一致性体验,如果不支持所请求的组合,bindToLifecycle调用将抛出IllegalArgumentException,而不是默默忽略功能请求。应使用CameraInfo#isFeatureGroupSupportedAPI(详见下文)预先查询此结果。preferredFeatureGroup:对于理想但可选的功能,请使用此值,例如当您想要实现默认的“高品质”模式时。您提供一个按优先级排序的所需功能列表,CameraX 会自动启用设备支持的优先级最高的组合。
- CameraInfo#isFeatureGroupSupported():这是用于明确检查是否支持某个功能组的核心查询方法,非常适合在应用界面中仅向用户提供受支持的功能选项。您需要向其传递一个
SessionConfig,它会返回一个布尔值,指明该组合是否受支持。如果您打算绑定具有所需功能的SessionConfig,应先使用此 API 确保其受支持。
实际应用中的实现
下面我们来看看如何使用这些组件来打造更好的相机体验。
场景 1:“尽力而为”的高画质模式
如果您想默认启用尽可能好的功能,可以向 preferredFeatureGroup 提供优先级列表。在此示例中,我们告知 CameraX 优先考虑 HDR,然后是 60 FPS,最后是预览防抖。CameraX 会处理检查所有可能组合并选择设备支持的最佳组合的复杂性。
例如,如果设备可以同时处理 HDR 和 60 FPS,但不能处理预览防抖,CameraX 将启用前两项并舍弃第三项。这样一来,您无需编写复杂的设备专用检查,即可获得尽可能出色的体验。
cameraProvider.bindToLifecycle(
lifecycleOwner,
cameraSelector,
SessionConfig(
useCases = listOf(preview, videoCapture),
// The order of features in this list determines their priority.
// CameraX will enable the best-supported combination based on these
// priorities: HDR_HLG10 > FPS_60 > Preview Stabilization.
preferredFeatureGroup =
listOf(HDR_HLG10, FPS_60, PREVIEW_STABILIZATION),
).apply {
// (Optional) Get a callback with the enabled features
// to update your UI.
setFeatureSelectionListener { selectedFeatures ->
updateUiIndicators(selectedFeatures)
}
}
)对于此代码段,CameraX 将尝试按以下优先级顺序启用功能组合,并选择设备完全支持的第一个功能组合:
- HDR + 60 FPS + 预览防抖
- HDR + 60 FPS
- HDR + 预览防抖
- HDR
- 60 FPS + 预览防抖
- 60 FPS
- 预览防抖
- 以上功能均不适用
场景 2:构建响应式界面
如需创建可响应用户选择并防止用户选择不受支持的功能组合的界面,您可以直接查询支持情况。以下函数会检查哪些功能与用户的当前选择不兼容,以便您停用相应的界面元素。
/**
* Returns a list of features that are NOT supported in combination
* with the currently selected features.
*/
fun getUnsupportedFeatures(
currentFeatures: Set<GroupableFeature>
): Set<GroupableFeature> {
val unsupportedFeatures = mutableSetOf<GroupableFeature>()
val appFeatureOptions = setOf(HDR_HLG10, FPS_60, PREVIEW_STABILIZATION)
// Iterate over every available feature option in your app.
appFeatureOptions.forEach { featureOption ->
// Skip features the user has already selected.
if (currentFeatures.contains(featureOption)) return@forEach
// Check if adding this new feature is supported.
val isSupported = cameraInfo.isFeatureGroupSupported(
SessionConfig(
useCases = useCases,
// Check the new feature on top of existing ones.
requiredFeatureGroup = currentFeatures + featureOption
)
)
if (!isSupported) {
unsupportedFeatures.add(featureOption)
}
}
return unsupportedFeatures
}然后,您可以将此逻辑连接到 ViewModel 或界面控制器,以响应用户输入并重新绑定相机,确保配置正常运行。
// Invoked when user turns some feature on/off.
fun onFeatureChange(currentFeatures: Set<GroupableFeature>) {
// Identify features that are unsupported with the current selection.
val unsupportedFeatures = getUnsupportedFeatures(currentFeatures)
// Update app UI so that users can't enable them.
updateDisabledFeatures(unsupportedFeatures)
// Since the UI now only allows selecting supported feature combinations,
// `currentFeatures` is always valid. This allows setting
// `requiredFeatureGroup` directly, without needing to re-check for
// support or set a feature selection listener.
cameraProvider.bindToLifecycle(
lifecycleOwner,
cameraSelector,
SessionConfig(
useCases = listOf(preview, videoCapture),
requiredFeatureGroup = currentFeatures,
)
)
}如需查看这些概念在实际应用中的效果,您可以探索我们的内部测试应用。该应用完整实现了上述“尽力而为”和“响应式界面”两种场景。
请注意:这是一个测试应用,并非官方支持的示例。虽然它是 Feature Group API 的绝佳参考资料,但尚未针对生产用途进行完善。
立即开始使用
功能组 API 消除了使用高级相机功能时的模糊性。通过提供一种确定性的方式来查询功能支持,您可以放心地构建更强大、更可靠的相机应用。
该 API 在 CameraX 1.5 中以实验性 API 的形式提供,计划在 1.6 版本中完全稳定,并且后续会提供更多支持和改进。
如需了解详情,请参阅官方文档。我们迫不及待地想看看您的作品,也期待您的反馈。请通过以下渠道分享您的想法并报告任何问题:
继续阅读
-
产品资讯
我们很高兴地宣布,Android XR 现已正式支持 Unreal Engine 和 Godot。我们还推出了旨在提高您的工作效率并实现全新 XR 功能的新工具:Android XR Engine Hub 和 Android XR Interaction Framework。
Luke Hopkins • 阅读用时:4 分钟
-
产品资讯
随着 Android 17 的发布,我们正在向自适应优先开发标准过渡。您的用户不再依赖单一的设备形态,而是在一天中不断切换手机、可折叠设备、平板电脑、笔记本电脑、车载显示屏和沉浸式 XR 环境。
Fahd Imtiaz • 阅读用时:4 分钟
-
产品资讯
我们很高兴与您分享 Google TV 功能和开发者工具,这些功能和工具旨在提高您内容的发现率,并为您的应用做好准备,以迎接未来的电视体验。
Paul Lammertsma • 阅读用时:4 分钟
随时了解最新动态
每周通过电子邮件接收最新的 Android 开发洞见。