Extensions API

CameraX 提供 Extension API,用以存取手機、平板電腦等各款 Android 裝置的以下特效 (由製造商提供)。

  • 自動模式:根據拍攝情境自動調整最終圖片。舉例來說,如果製造商的程式庫提供低光源偵測功能,便可在拍照時切換至低光源模式或 HDR 模式;拍攝肖像照時,程式庫也可能會自動套用修容模式。在自動模式中,製造商資料庫負責決定拍攝模式。
  • 散景模式:散景模式可讓前景字元看起來更清晰,並模糊相片背景。這種模式通常用於拍攝人物照,效果近於使用大鏡頭相機所拍攝的人像。
  • 修容模式:用於拍攝靜態圖片,調整臉部膚色、幾何圖形等。
  • 高動態範圍模式:高動態範圍模式能在光線差異較大的場景中,拍攝出清晰可見的照片。舉例來說,在明亮的窗戶前拍攝物體相片時,使用 HDR 模式可讓窗中場景清晰可見;然而使用一般模式就會曝光不足。為取得清晰的照片,HDR 拍攝一張照片通常需要較長作業時間,而且使用者無法決定拍攝時間長短,根據使用的 HDR 方法,也可能產生不同拍攝成果。
  • 夜景模式:在低光源環境中 (通常是夜間),取得最佳靜態圖片。

如要讓裝置使用這些製造商擴充功能,裝置必須滿足下列條件:

  • 裝置的 ROM 具備支援效果的程式庫。
  • 當前裝置已安裝 ROM 程式庫。
  • 裝置已搭載程式庫需要的作業系統版本。

只要裝置「支援」且「已安裝」某項擴充功能,該擴充功能就會優先啟用,否則會以優雅降級的方式處置。

製造商不須執行個別效果和功能。只要非製造商提供的功能都會預設使用 CameraX。如執行預設功能後,結果顯示無法使用,則不啟用該功能。

擴充架構

下圖顯示搭載 CameraX 的擴充架構。

圖 1 可擴充的 CameraX 架構

擴充功能獨立於 CameraX 的 Camera2 核心之外。在架構圖中,紅色箭頭代表使用者觸發擴充功能 (例如 HDR 拍攝模式) 時的主資料流。

啟用圖片拍攝與預覽效果

使用 Extensions 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

發布新版 Extensions API (1.0.0-alpha26 版本) 後,我們目前已淘汰於 2019 年 8 月發布的舊版 Extensions API。自 1.0.0-alpha28 版本起,舊版 Extensions API 已從程式庫中移除。如已使用新版 Extension API 的應用程式,則須取得已啟用擴充功能的 CameraSelector,並將其用於繫結功能。

如使用舊版 Extension API 的應用程式,則應遷移至新版 Extensions API,以確保與日後的 CameraX 版本相容。

其他資源

如要進一步瞭解 CameraX,請參閱下列其他資源。

程式碼研究室

  • 開始使用 CameraX
  • 程式碼範例

  • CameraX 範例應用程式
  • 其他參考資料

    CameraX 製造商擴充功能

    CameraX 製造商擴充功能驗證工具