
Android CameraX 的設計旨在幫助您簡化相機應用的開發(fā)工作。隨著對 CameraX 不斷的開發(fā),相機應用的開發(fā)者們向我們展示了他們的激情和熱忱,當前的 API 中已經融入了許多很棒的創(chuàng)意,例如值得稱贊的 CameraX Extensions API。最近我們采納了開發(fā)者社區(qū)的意見,對擴展進行了重構,如今有了新的 ExtensionsManager,您只需兩行代碼就可以使用這些擴展!本文將介紹如何在您的應用中使用 Extensions API。
CameraX Extensions
Android 設備配備了強大的相機,制造商們投入了大量精力將眾多前沿的功能特性或特效融入這些相機設備中。過去,這些強大的功能只能由設備的原生相機應用提供。如今,憑借 CameraX Extensions API,第三方開發(fā)者可以通過一個通用的、簡單的接口來訪問這些強大的相機功能。

CameraX Extensions 涵蓋的內容
1.0.0 版本的 CameraX Extensions 包括一些最常見的內置相機特效:
- BOKEH (焦外成像): 在人像模式下拍攝照片時,讓前景人物更清晰。
- HDR (高動態(tài)范圍): 拍照時使用不同的自動曝光 (AE) 配置,以獲得最佳效果。
- NIGHT (夜間): 在低照度環(huán)境下 (通常是在夜間) 捕獲最佳靜態(tài)圖像。
- FACE RETOUCH (臉部照片修復): 拍攝靜態(tài)圖像時,修飾臉部膚色、輪廓等。
- AUTO (自動): 根據周圍的景色自動調整最終圖像。
讓我們來看幾組在 Android 手機上拍攝的照片,拍照時分別啟用和禁用了由 CameraX Extensions API 提供的特效。
BOKEH 模式的例子

HDR 模式的例子

NIGHT 模式例子

視覺上的差異是很明顯的。您可以使用 CameraX Extensions API 在您自己的應用中實現(xiàn)這些圖像的效果。
現(xiàn)在讓我們看看如何將 CameraX 的 API 集成到您的應用中。
Extensions API
在現(xiàn)有的 CameraX 應用中,首先您可以引入 camera-extensions Jetpack 庫來添加 CameraX Extensions:
dependencies {
// 與 Extensions 庫版本號相匹配的 CameraX 核心庫
implementation 'androidx.camera:camera-core:1.1.0-alpha08'
implementation 'androidx.camera:camera-camera2:1.1.0-alpha08'
implementation 'androidx.camera:camera-lifecycle:1.1.0-alpha08'
// CameraX Extensions 庫
implementation 'androidx.camera:camera-extensions:1.0.0-alpha28'
// 其他依賴項
implementation('androidx.concurrent:concurrent-futures-ktx:1.1.0')
…
}
接下來,通過以下步驟集成 Extensions:
- 獲取 ExtensionsManager 實例。
- 檢查目標設備是否支持需要用到的擴展模式;
- 獲取一個啟用擴展的 CameraSelector;
- 使用啟用擴展的 CameraSelector 調用 bindToLifecycle。
獲取 ExtensionsManager 實例
第一步是用擴展庫的 getInstance(Context) API 獲得一個 ExtensionsManager 實例。這個 API 返回一個 ListenableFuture,我們可以在 Kotlin 掛起函數中使用 await() 來獲取結果以避免阻塞主線程。(注意: 在 ListenableFuture 上使用 await() 須引入 androidx.concurrent:concurrent-futures-ktx: 1.1.0 依賴項。)
// 創(chuàng)建擴展管理器(使用 Jetpack Concurrent 庫)
val extensionsManager = ExtensionsManager.getInstance(context).await()
通過 ExtensionsManager,您可以確定設備是否支持某一特定的擴展模式,并為其獲取一個啟用擴展的 CameraSelector。請注意以下幾點:
- ExtensionsManager 是一個進程范圍的全局資源: 一個進程中只存在一個 ExtensionsManager 實例。
- ExtensionsManager 始終存在: 無論底層設備是否支持擴展,CameraX 都提供一個有效的 ExtensionsManager 實例。
檢查擴展模式可用性
通過 ExtensionsManager,使用 isExtensionAvailable(CameraProvider, CameraSelector, int) 函數檢查擴展的可用性: 如果設備上存在任何經由 CameraSelector 過濾的相機支持所查詢的擴展,則返回 true,否則返回 false。
// 獲取相機設備來檢查是否支持擴展
val cameraSelector = CameraSelector.DEFAULT_BACK_CAMERA
// 檢查是否支持 BOKEH
if (extensionsManager.isExtensionAvailable(
cameraProvider,
cameraSelector,
ExtensionMode.BOKEH
)) {
...
}
獲取啟用擴展的 CameraSelector
一旦您確認了設備支持該擴展模式,就可以用 getExtensionEnabledCameraSelector(CameraProvider, CameraSelector, int) 函數獲取一個啟用擴展的 CameraSelector。此函數返回啟用擴展的 CameraSelector,其包含關于指定擴展模式的所有詳細信息。
val bokehCameraSelector = extensionsManager
.getExtensionEnabledCameraSelector(
cameraProvider, cameraSelector, ExtensionMode.BOKEH)
使用啟用擴展的 CameraSelector 調用 bindToLifecycle()
最后一步是使用 bindToLifecycle() 將您的用例與啟用擴展的 CameraSelector 綁定。使用啟用擴展的 CameraSelector 如同使用普通的 CameraSelector 一樣,例如使用 DEFAULT_BACK_CAMERA 或 DEFAULT_FRONT_CAMERA。當使用啟用擴展的 CameraSelector綁定用例時,CameraX 會直接在相機上啟用指定的擴展模式。例如,當綁定到 Preview 時,擴展效果被應用到預覽中,或者應用到由所綁定的 ImageCapture 所捕獲的圖像上。
// 將開啟了 BOKEH 的相機選擇器綁定到用例上
val imageCapture = ImageCapture.Builder().build()
val preview = Preview.Builder().build()
cameraProvider.bindToLifecycle(
lifecycleOwner,
bokehCameraSelector,
imageCapture,
preview
)
使用 Extensions API 的樣例代碼
Extensions API 示例的完整代碼如下:
fun onCreate() {
lifecycleScope.launch {
// 創(chuàng)建 cameraProvider
val cameraProvider = ProcessCameraProvider.getInstance(context).await()
// 創(chuàng)建 extensionsManager(使用 Jetpack Concurrent 庫)
val extensionsManager =
ExtensionsManager.getInstance(context).await()
// 獲取相機設備來檢查是否支持擴展
val cameraSelector = CameraSelector.DEFAULT_BACK_CAMERA
// 檢查是否支持 BOKEH
if (extensionsManager.isExtensionAvailable(
cameraProvider,
cameraSelector,
ExtensionMode.BOKEH
)) {
// 在啟用不同擴展模式之前解除所有用例的綁定
cameraProvider.unbindAll()
// 獲取啟用了 BOKEH 的相機選擇器
val bokehCameraSelector = extensionsManager
.getExtensionEnabledCameraSelector(
cameraProvider,
cameraSelector,
ExtensionMode.BOKEH
)
// 將開啟了 BOKEH 的相機選擇器綁定到用例上
val imageCapture = ImageCapture.Builder().build()
val preview = Preview.Builder().build()
cameraProvider.bindToLifecycle(
lifecycleOwner,
bokehCameraSelector,
imageCapture,
preview
)
}
}
}
Extensions API 對核心模塊的依賴
CameraX Extensions API 是在 camera-extensions 庫中實現(xiàn)的,并且它依賴 CameraX 核心模塊 (core、camera2 和 lifecycle)。使用 CameraX Extensions 時,請務必使用與您正在使用的 CameraX 核心模塊 相同的發(fā)布包 中的版本。例如,要使用 camera-extensions:1.0.0-alpha28,則您必須在應用的依賴列表中包含 1.0.0-alpha08 版本的 camera-lifecycle、camera-core 和 camera-camera2,因為它們是于 2021 年 8 月 18 日在同一軟件包中發(fā)布的。
支持擴展的設備
為了能使用 CameraX Extensions API,設備制造商需要實現(xiàn) CameraX Vendor Extensions 接口。您可以在 CameraX 設備頁面 上找到支持 CameraX Extensions API 的部分設備列表。請注意,這不是一個詳盡的列表。如果您的設備被列出,但可用性檢查返回了 false,您可能需要將您的設備更新到制造商的最新 ROM 版本。
除了支持擴展的設備列表外,從 Android 12 開始,您還可以通過檢查 Android 屬性 ro.camerax.extensions.enabled 來確定設備是否支持 CameraX Extensions。
移除舊版 Extensions API
2019 年 8 月發(fā)布的舊版 Extensions API 現(xiàn)已廢棄。這個舊版的 Extensions API 提供了擴展器類,需要將擴展相關的配置應用到每個 Preview 和 ImageCapture 用例上。舊版的擴展器設計可能會導致開發(fā)人員忘記要在 Preview 或 ImageCapture 上啟用擴展模式,并可能導致非預期的行為。
新的 CameraX Extensions 庫在 1.0.0-alpha26 中引入。較新的 Extensions API 將擴展綁定從用例切換到目標相機,使用起來更加方便。請務必遷移以利用新的 Extensions API。
我們特別感謝那些幫助實現(xiàn) CameraX Extensions API 的出色的 Android 相機開發(fā)者和設備制造商!如果您想了解 CameraX 的最新進展,請加入 Android CameraX 討論組。
更多信息
- CameraX Extensions API 指南
- Extensions API 參考
- 擴展測試應用
- CameraX 發(fā)布說明
- 開始使用 CameraX
- CameraX Github 樣例代碼
歡迎您 點擊這里 向我們提交反饋,或分享您喜歡的內容、發(fā)現(xiàn)的問題。您的反饋對我們非常重要,感謝您的支持!