現代相機應用程式的特色在於強大且重疊的功能。使用者期望能錄製出色的 HDR 影片、以 60 FPS 捕捉流暢動作,並透過預覽畫面穩定功能取得極致流暢的影片,而且通常希望這些功能可以同時運作。
但開發人員都知道,實際情況更為複雜。如何保證特定裝置確實支援指定組合?過去,啟用多項功能往往像是一場賭博。您可以檢查個別功能支援,但合併這些功能可能會導致未定義的行為,或更糟的是,相機會話群組失敗。這種不確定性迫使開發人員採取保守做法,導致使用者無法在支援的裝置上獲得最佳體驗。
舉例來說,只有極少數的高階裝置能同時穩定支援 HDR 和 60 FPS 影片。因此,大多數應用程式會避免同時啟用這兩項功能,以免在多數手機上造成不佳的使用者體驗。
為解決這個問題,我們推出了 CameraX 中的 Feature Group,這個新 API 可消除這類不確定性。現在,您可以在設定相機之前,查詢是否支援特定功能組合,或直接告訴 CameraX 您的優先順序,讓 CameraX 為您啟用支援度最佳的組合。
CameraX 新手
在深入探討新的 Feature Group API 之前,我們先快速回顧一下 CameraX。CameraX 是 Jetpack 支援程式庫,旨在協助應用程式開發人員輕鬆開發相機應用程式。並提供一致且易於使用的 API 介面,適用於大多數 Android 裝置,具備 Android 6.0 (API 級別 23) 的回溯相容性。如果您是第一次使用 CameraX,建議您參閱官方說明文件,並試用程式碼實驗室,瞭解如何開始使用。
Feature Group API 的用途
您不必再賭運氣,可以放心提供最佳相機體驗,例如在支援的硬體 (如 Pixel 10 Pro) 上同時啟用 HDR 和 60 FPS 影片,同時在不支援該組合的裝置上,也能妥善避免錯誤。
您可以使用 Feature Group API 執行下列操作:
- 建構更聰明的動態 UI:根據即時硬體支援,智慧啟用或停用 UI 設定。舉例來說,如果使用者啟用 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():這是核心查詢方法,可明確檢查是否支援功能群組,非常適合在應用程式 UI 中,只向使用者提供支援的功能選項。您傳遞
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 + 預覽防震功能
- 高動態範圍
- 60 FPS + 預覽防震功能
- 每秒 60 個影格
- 預覽防震功能
- 以上皆非
情境 2:建構回應式 UI
如要建立可回應使用者選項,並防止使用者選取不支援功能組合的使用者介面,您可以直接查詢支援。以下函式會檢查哪些功能與使用者「目前」選取的項目不相容,以便停用對應的 UI 元素。
/**
* 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 或 UI 控制器,以便回應使用者輸入內容,並使用保證可運作的設定重新繫結相機。
// 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,
)
)
}如要在實際運作的應用程式中查看這些概念,可以探索我們的內部測試應用程式。該應用程式提供上述「盡力而為」和「反應式 UI」情境的完整實作。
請注意:這是測試應用程式,並非官方支援的範例。雖然這份文件是 Feature Group API 的絕佳參考資料,但尚未經過完善處理,不適合用於正式環境。
立即開始使用
Feature Group API 可消除使用進階相機功能時的模糊地帶。只要提供確定性的功能支援查詢方式,就能安心建構更強大可靠的相機應用程式。
這項 API 在 CameraX 1.5 中為實驗功能,預計在 1.6 版本中完全穩定,並將提供更多支援和改善。
詳情請參閱官方說明文件。我們期待看到你的精彩傑作,也歡迎你提供寶貴意見。歡迎透過下列管道分享你的想法或回報任何問題:
-
產品最新消息今天,我們在 Android 開發人員高峰會上宣布,將廣泛提供多項工具和 API,旨在消除日常摩擦,讓您更靈活地建構出色的 Android 應用程式。
Matthew McCullough • 閱讀時間:4 分鐘 -
產品最新消息Android Studio Rabbit 2 穩定版已推出,可供您在正式環境中使用。此版本包含多項重要功能,可提升開發效率,例如「自備代理」、全新 XR 模擬器功能、LeakCanary 更新、全新代理技能管理工具、AI 程式碼審查等。
Matthew Warner • 閱讀時間:3 分鐘 -
產品最新消息如果應用程式指定即將推出的 Android 版本,將無法再透過 WRITE_CONTACTS 權限直接寫入聯絡人資料。
Roxanna Aliabadi Walker • 閱讀時間:6 分鐘
每週透過電子郵件接收 Android 開發人員的最新深入分析。