สถาปัตยกรรม CameraX

หน้านี้ครอบคลุมสถาปัตยกรรมของ CameraX ซึ่งรวมถึงโครงสร้าง วิธีการทำงานกับ API วิธีการทำงานกับวงจร และวิธีรวม Use Case

โครงสร้าง CameraX

คุณใช้ CameraX เพื่อเชื่อมต่อกับกล้องของอุปกรณ์ผ่าน การแยกส่วนที่เรียกว่า Use Case ได้ กรณีการใช้งานที่พร้อมใช้งานมีดังนี้

  • แสดงตัวอย่าง: รับพื้นผิวเพื่อแสดงตัวอย่าง เช่น PreviewView
  • การวิเคราะห์รูปภาพ: จัดเตรียมบัฟเฟอร์ที่ CPU เข้าถึงได้สำหรับการวิเคราะห์ เช่น สำหรับ แมชชีนเลิร์นนิง
  • การจับภาพ: จับภาพและบันทึกรูปภาพ
  • การจับภาพวิดีโอ: จับภาพวิดีโอและเสียงด้วย VideoCapture

คุณสามารถรวม Use Case และเปิดใช้งานพร้อมกันได้ เช่น แอปอาจอนุญาตให้ ผู้ใช้ดูรูปภาพที่กล้องเห็นโดยใช้กรณีการใช้งานตัวอย่าง มีกรณีการใช้งานการวิเคราะห์รูปภาพที่ระบุว่าผู้คนในรูปภาพกำลังยิ้มหรือไม่ และมีกรณีการใช้งานการจับภาพเพื่อถ่ายรูปเมื่อผู้คนยิ้ม

โมเดล API

หากต้องการใช้ไลบรารี คุณต้องระบุสิ่งต่อไปนี้

  • กรณีการใช้งานที่ต้องการพร้อมตัวเลือกการกำหนดค่า
  • สิ่งที่ต้องทำกับข้อมูลเอาต์พุตโดยการแนบ Listener
  • โฟลว์ที่ต้องการ เช่น เมื่อใดควรเปิดใช้กล้องและเมื่อใดควรสร้างข้อมูล โดยการเชื่อมโยง Use Case กับวงจรของสถาปัตยกรรม Android

การเขียนแอป CameraX ทำได้ 2 วิธี ได้แก่ CameraController (เหมาะหากต้องการวิธีที่ง่ายที่สุดในการใช้ CameraX) หรือ CameraProvider (เหมาะหากต้องการความยืดหยุ่นมากขึ้น)

CameraController

CameraController มีฟังก์ชันหลักส่วนใหญ่ของ CameraX ในคลาสเดียว โดยไม่ต้องใช้โค้ดการตั้งค่ามากนัก และจะจัดการการเริ่มต้นกล้อง การจัดการ Use Case การหมุนเป้าหมาย การแตะเพื่อโฟกัส การบีบนิ้วเพื่อซูม และอื่นๆ โดยอัตโนมัติ คลาสที่เป็นรูปธรรมซึ่งขยาย CameraController คือ LifecycleCameraController

Kotlin

val previewView: PreviewView = viewBinding.previewView
var cameraController = LifecycleCameraController(baseContext)
cameraController.bindToLifecycle(this)
cameraController.cameraSelector = CameraSelector.DEFAULT_BACK_CAMERA
previewView.controller = cameraController

Java

PreviewView previewView = viewBinding.previewView;
LifecycleCameraController cameraController = new LifecycleCameraController(baseContext);
cameraController.bindToLifecycle(this);
cameraController.setCameraSelector(CameraSelector.DEFAULT_BACK_CAMERA);
previewView.setController(cameraController);

UseCase เริ่มต้นสำหรับ CameraController คือ Preview, ImageCapture และ ImageAnalysis หากต้องการปิด ImageCapture หรือ ImageAnalysis หรือเปิด VideoCapture ให้ใช้เมธอด setEnabledUseCases()

ดูการใช้งาน CameraController เพิ่มเติมได้ที่ ตัวอย่างตัวสแกนคิวอาร์โค้ด หรือ วิดีโอพื้นฐานเกี่ยวกับ CameraController

CameraProvider

CameraProvider ยังคงใช้งานง่าย แต่เนื่องจากนักพัฒนาแอปจัดการการตั้งค่าเพิ่มเติม จึงมีโอกาสมากขึ้นในการปรับแต่งการกำหนดค่า เช่น การเปิดใช้การหมุนรูปภาพเอาต์พุตหรือการตั้งค่ารูปแบบรูปภาพเอาต์พุตใน ImageAnalysis นอกจากนี้ คุณยังใช้ Surface ที่กำหนดเองสำหรับตัวอย่างกล้องได้ด้วย ซึ่งจะช่วยให้มีความยืดหยุ่นมากขึ้น ในขณะที่ CameraController กำหนดให้คุณต้องใช้ PreviewView การใช้โค้ด Surface ที่มีอยู่จะเป็นประโยชน์หากโค้ดนั้น เป็นอินพุตไปยังส่วนอื่นๆ ของแอปอยู่แล้ว

คุณกำหนดค่า Use Case โดยใช้set()เมธอด และทำให้เสร็จสมบูรณ์ด้วยเมธอด build() ออบเจ็กต์กรณีการใช้งานแต่ละรายการจะมีชุด API เฉพาะกรณีการใช้งาน ตัวอย่างเช่น กรณีการใช้งานการจับภาพจะมีการเรียกใช้เมธอด takePicture()

แทนที่จะให้แอปพลิเคชันวางการเรียกเมธอดเริ่มต้นและหยุดที่เฉพาะเจาะจงใน onResume() และ onPause() แอปพลิเคชันจะระบุวงจรเพื่อเชื่อมโยง กล้องด้วยการใช้ cameraProvider.bindToLifecycle() จากนั้นวงจรนั้นจะแจ้งให้ CameraX ทราบเมื่อใดควรตั้งค่าเซสชันการจับภาพของกล้อง และตรวจสอบว่าการเปลี่ยนแปลงสถานะของกล้องเป็นไปอย่างเหมาะสมเพื่อให้ตรงกับการเปลี่ยนวงจร

ดูขั้นตอนการติดตั้งใช้งานสำหรับกรณีการใช้งานแต่ละกรณีได้ที่ติดตั้งใช้งาน การแสดงตัวอย่าง วิเคราะห์ รูปภาพ การ จับภาพ และการจับภาพวิดีโอ

กรณีการใช้งานการแสดงตัวอย่างจะโต้ตอบกับ Surfaceเพื่อแสดง แอปพลิเคชัน สร้างกรณีการใช้งานด้วยตัวเลือกการกำหนดค่าโดยใช้โค้ดต่อไปนี้

Kotlin

val preview = Preview.Builder().build()
val viewFinder: PreviewView = findViewById(R.id.previewView)

// The use case is bound to an Android Lifecycle with the following code
val camera = cameraProvider.bindToLifecycle(lifecycleOwner, cameraSelector, preview)

// PreviewView creates a surface provider and is the recommended provider
preview.setSurfaceProvider(viewFinder.getSurfaceProvider())

Java

Preview preview = new Preview.Builder().build();
PreviewView viewFinder = findViewById(R.id.view_finder);

// The use case is bound to an Android Lifecycle with the following code
Camera camera = cameraProvider.bindToLifecycle(lifecycleOwner, cameraSelector, preview);

// PreviewView creates a surface provider, using a Surface from a different
// kind of view will require you to implement your own surface provider.
preview.previewSurfaceProvider = viewFinder.getSurfaceProvider();

ดูโค้ดตัวอย่างเพิ่มเติมได้ที่แอปตัวอย่าง CameraX อย่างเป็นทางการ

วงจรของ CameraX

CameraX จะสังเกตวงจรของออบเจ็กต์เพื่อพิจารณาว่าจะเปิดกล้องเมื่อใด จะสร้างเซสชันการจับภาพเมื่อใด และจะหยุดและปิดเมื่อใด API กรณีการใช้งานมี การเรียกเมธอดและ Callback เพื่อตรวจสอบความคืบหน้า

ดังที่อธิบายไว้ในรวม Use Case คุณสามารถเชื่อมโยง Use Case บางอย่างเข้ากับวงจรเดียวได้ เมื่อแอปต้องรองรับกรณีการใช้งานที่ ใช้ร่วมกันไม่ได้ คุณจะทำอย่างใดอย่างหนึ่งต่อไปนี้ได้

  • จัดกลุ่มกรณีการใช้งานที่เข้ากันได้ไว้ด้วยกันเป็นFragment มากกว่า 1 รายการ แล้วสลับไปมาระหว่าง Fragment
  • สร้างคอมโพเนนต์วงจรที่กำหนดเองและใช้เพื่อควบคุมวงจรของกล้องด้วยตนเอง

หากแยกเจ้าของวงจรของ Use Case ของการดูและกล้อง (เช่น หากคุณใช้วงจรที่กำหนดเองหรือretain fragment) คุณจะต้องตรวจสอบว่าได้ยกเลิกการเชื่อมโยง Use Case ทั้งหมดจาก CameraX โดยใช้ ProcessCameraProvider.unbindAll() หรือโดยการยกเลิกการเชื่อมโยง Use Case แต่ละรายการแยกกัน หรือเมื่อเชื่อมโยงกรณีการใช้งานกับวงจรของแอป คุณจะให้ CameraX จัดการการเปิดและปิดเซสชันการจับภาพ รวมถึงยกเลิกการเชื่อมโยงกรณีการใช้งานได้

หากฟังก์ชันการทำงานทั้งหมดของกล้องสอดคล้องกับวงจรของคอมโพเนนต์เดียวที่รับรู้ถึงวงจร เช่น AppCompatActivity หรือ Fragment AppCompat การใช้วงจรของคอมโพเนนต์นั้นเมื่อเชื่อมโยง Use Case ที่ต้องการทั้งหมดจะช่วยให้มั่นใจได้ว่าฟังก์ชันการทำงานของกล้องพร้อมใช้งานเมื่อคอมโพเนนต์ที่รับรู้ถึงวงจรทำงานอยู่ และจะมีการทิ้งอย่างปลอดภัยโดยไม่ใช้ทรัพยากรใดๆ

LifecycleOwner ที่กำหนดเอง

สำหรับกรณีขั้นสูง คุณสามารถสร้าง LifecycleOwnerที่กำหนดเองเพื่อเปิดใช้แอป ให้ควบคุมวงจรเซสชัน CameraX อย่างชัดเจนแทนที่จะเชื่อมโยงกับ LifecycleOwnerมาตรฐานของ Android

ตัวอย่างโค้ดต่อไปนี้แสดงวิธีสร้าง LifecycleOwner ที่กำหนดเองแบบง่าย

Kotlin

class CustomLifecycle : LifecycleOwner {
    private val lifecycleRegistry: LifecycleRegistry

    init {
        lifecycleRegistry = LifecycleRegistry(this);
        lifecycleRegistry.markState(Lifecycle.State.CREATED)
    }
    ...
    fun doOnResume() {
        lifecycleRegistry.markState(State.RESUMED)
    }
    ...
    override fun getLifecycle(): Lifecycle {
        return lifecycleRegistry
    }
}

Java

public class CustomLifecycle implements LifecycleOwner {
    private LifecycleRegistry lifecycleRegistry;
    public CustomLifecycle() {
        lifecycleRegistry = new LifecycleRegistry(this);
        lifecycleRegistry.markState(Lifecycle.State.CREATED);
    }
   ...
   public void doOnResume() {
        lifecycleRegistry.markState(State.RESUMED);
    }
   ...
    public Lifecycle getLifecycle() {
        return lifecycleRegistry;
    }
}

การใช้ LifecycleOwner นี้จะช่วยให้แอปของคุณวางการเปลี่ยนสถานะในจุดที่ต้องการในโค้ดได้ ดูข้อมูลเพิ่มเติมเกี่ยวกับการใช้ฟังก์ชันนี้ในแอปได้ที่การใช้ LifecycleOwner ที่กำหนดเอง

กรณีการใช้งานพร้อมกัน

กรณีการใช้งานสามารถทำงานพร้อมกันได้ แม้ว่ากรณีการใช้งานจะเชื่อมโยงกับวงจร ได้ตามลำดับ แต่การเชื่อมโยงกรณีการใช้งานทั้งหมดด้วยการเรียกใช้ CameraProcessProvider.bindToLifecycle() ครั้งเดียวจะดีกว่า ดูข้อมูลเพิ่มเติมเกี่ยวกับแนวทางปฏิบัติแนะนำสำหรับการเปลี่ยนแปลงการกำหนดค่าได้ที่จัดการการเปลี่ยนแปลงการกำหนดค่า

ในตัวอย่างโค้ดต่อไปนี้ แอปจะระบุ Use Case 2 รายการที่จะสร้าง และเรียกใช้พร้อมกัน นอกจากนี้ยังระบุวงจรที่จะใช้สำหรับทั้ง 2 กรณีการใช้งาน เพื่อให้ทั้ง 2 กรณีเริ่มต้นและหยุดตามวงจร

Kotlin

private lateinit var imageCapture: ImageCapture

override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)
    setContentView(R.layout.activity_main)

    val cameraProviderFuture = ProcessCameraProvider.getInstance(this)

    cameraProviderFuture.addListener(Runnable {
        // Camera provider is now guaranteed to be available
        val cameraProvider = cameraProviderFuture.get()

        // Set up the preview use case to display camera preview.
        val preview = Preview.Builder().build()

        // Set up the capture use case to allow users to take photos.
        imageCapture = ImageCapture.Builder()
                .setCaptureMode(ImageCapture.CAPTURE_MODE_MINIMIZE_LATENCY)
                .build()

        // Choose the camera by requiring a lens facing
        val cameraSelector = CameraSelector.Builder()
                .requireLensFacing(CameraSelector.LENS_FACING_FRONT)
                .build()

        // Attach use cases to the camera with the same lifecycle owner
        val camera = cameraProvider.bindToLifecycle(
                this as LifecycleOwner, cameraSelector, preview, imageCapture)

        // Connect the preview use case to the previewView
        preview.setSurfaceProvider(
                previewView.getSurfaceProvider())
    }, ContextCompat.getMainExecutor(this))
}

Java

private ImageCapture imageCapture;

@Override
public void onCreate(@Nullable Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);

    PreviewView previewView = findViewById(R.id.previewView);

    ListenableFuture<ProcessCameraProvider> cameraProviderFuture =
            ProcessCameraProvider.getInstance(this);

    cameraProviderFuture.addListener(() -> {
        try {
            // Camera provider is now guaranteed to be available
            ProcessCameraProvider cameraProvider = cameraProviderFuture.get();

            // Set up the view finder use case to display camera preview
            Preview preview = new Preview.Builder().build();

            // Set up the capture use case to allow users to take photos
            imageCapture = new ImageCapture.Builder()
                    .setCaptureMode(ImageCapture.CAPTURE_MODE_MINIMIZE_LATENCY)
                    .build();

            // Choose the camera by requiring a lens facing
            CameraSelector cameraSelector = new CameraSelector.Builder()
                    .requireLensFacing(lensFacing)
                    .build();

            // Attach use cases to the camera with the same lifecycle owner
            Camera camera = cameraProvider.bindToLifecycle(
                    ((LifecycleOwner) this),
                    cameraSelector,
                    preview,
                    imageCapture);

            // Connect the preview use case to the previewView
            preview.setSurfaceProvider(
                    previewView.getSurfaceProvider());
        } catch (InterruptedException | ExecutionException e) {
            // Currently no exceptions thrown. cameraProviderFuture.get()
            // shouldn't block since the listener is being called, so no need to
            // handle InterruptedException.
        }
    }, ContextCompat.getMainExecutor(this));
}

CameraX อนุญาตให้ใช้ Preview, VideoCapture, ImageAnalysis และ ImageCapture พร้อมกันได้ครั้งละ 1 อินสแตนซ์ นอกจากนี้

  • กรณีการใช้งานแต่ละรายการสามารถทำงานได้ด้วยตัวเอง เช่น แอปสามารถบันทึกวิดีโอ โดยไม่ต้องใช้ตัวอย่าง
  • เมื่อเปิดใช้ส่วนขยาย จะรับประกันว่าเฉพาะการผสมผสานระหว่าง ImageCapture และ Preview เท่านั้นที่จะใช้งานได้ ทั้งนี้ขึ้นอยู่กับการติดตั้งใช้งานของ OEM คุณอาจเพิ่ม ImageAnalysis ไม่ได้ และเปิดใช้ส่วนขยายสำหรับ Use Case ของ VideoCapture ไม่ได้ ดูรายละเอียดได้ที่เอกสารอ้างอิงส่วนขยาย
  • กล้องบางรุ่นอาจรองรับการผสมผสานใน โหมดความละเอียดต่ำกว่า แต่ไม่รองรับการผสมผสานเดียวกันใน ความละเอียดที่สูงกว่า ทั้งนี้ขึ้นอยู่กับความสามารถของกล้อง
  • ในอุปกรณ์ที่มีฮาร์ดแวร์กล้องระดับ FULL หรือต่ำกว่า การรวม Preview, VideoCapture และ ImageCapture หรือ ImageAnalysis อาจทำให้ CameraX ต้องทำซ้ำสตรีม PRIV ของกล้องสำหรับ Preview และ VideoCapture การทำซ้ำนี้เรียกว่าการแชร์สตรีม ซึ่งช่วยให้ใช้ฟีเจอร์เหล่านี้ได้พร้อมกัน แต่ต้องแลกมาด้วยความต้องการในการประมวลผลที่เพิ่มขึ้น คุณอาจ พบว่าเวลาในการตอบสนองนานขึ้นเล็กน้อยและอายุการใช้งานแบตเตอรี่ลดลง

ระดับฮาร์ดแวร์ที่รองรับ สามารถดึงข้อมูลได้จาก Camera2CameraInfo เช่น โค้ดต่อไปนี้ จะตรวจสอบว่ากล้องด้านหลังเริ่มต้นเป็นอุปกรณ์ LEVEL_3 หรือไม่

Kotlin

@androidx.annotation.OptIn(ExperimentalCamera2Interop::class)
fun isBackCameraLevel3Device(cameraProvider: ProcessCameraProvider) : Boolean {
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
        return CameraSelector.DEFAULT_BACK_CAMERA
            .filter(cameraProvider.availableCameraInfos)
            .firstOrNull()
            ?.let { Camera2CameraInfo.from(it) }
            ?.getCameraCharacteristic(CameraCharacteristics.INFO_SUPPORTED_HARDWARE_LEVEL) ==
            CameraCharacteristics.INFO_SUPPORTED_HARDWARE_LEVEL_3
    }
    return false
}

Java

@androidx.annotation.OptIn(markerClass = ExperimentalCamera2Interop.class)
Boolean isBackCameraLevel3Device(ProcessCameraProvider cameraProvider) {
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
        List\<CameraInfo\> filteredCameraInfos = CameraSelector.DEFAULT_BACK_CAMERA
                .filter(cameraProvider.getAvailableCameraInfos());
        if (!filteredCameraInfos.isEmpty()) {
            return Objects.equals(
                Camera2CameraInfo.from(filteredCameraInfos.get(0)).getCameraCharacteristic(
                        CameraCharacteristics.INFO_SUPPORTED_HARDWARE_LEVEL),
                CameraCharacteristics.INFO_SUPPORTED_HARDWARE_LEVEL_3);
        }
    }
    return false;
}

สิทธิ์

แอปของคุณจะต้องมีสิทธิ์ CAMERA หากต้องการ บันทึกรูปภาพลงในไฟล์ แอปจะต้องมีสิทธิ์ WRITE_EXTERNAL_STORAGE ด้วย ยกเว้นในอุปกรณ์ที่ใช้ Android 10 ขึ้นไป

ดูข้อมูลเพิ่มเติมเกี่ยวกับการกำหนดค่าสิทธิ์สำหรับแอปได้ที่ขอสิทธิ์ของแอป

ข้อกำหนด

CameraX มีข้อกำหนดขั้นต่ำของเวอร์ชันดังนี้

  • ระดับ API 21 ของ Android
  • คอมโพเนนต์สถาปัตยกรรมของ Android 1.1.1

สำหรับกิจกรรมที่รับรู้ถึงวงจร ให้ใช้ FragmentActivity หรือ AppCompatActivity

ประกาศทรัพยากร Dependency

หากต้องการเพิ่มทรัพยากร Dependency ใน CameraX คุณต้องเพิ่มที่เก็บ Google Maven ลงในโปรเจ็กต์

เปิดไฟล์ settings.gradle สำหรับโปรเจ็กต์ แล้วเพิ่มที่เก็บ google() ตามที่แสดงด้านล่าง

ดึงดูด

dependencyResolutionManagement {
    repositoriesMode.set(RepositoriesMode.FAIL_ON_PROJECT_REPOS)
    repositories {
        google()
        mavenCentral()
    }
}

Kotlin

dependencyResolutionManagement {
    repositoriesMode.set(RepositoriesMode.FAIL_ON_PROJECT_REPOS)
    repositories {
        google()
        mavenCentral()
    }
}

เพิ่มข้อมูลต่อไปนี้ที่ส่วนท้ายของบล็อก Android

ดึงดูด

android {
    compileOptions {
        sourceCompatibility JavaVersion.VERSION_1_8
        targetCompatibility JavaVersion.VERSION_1_8
    }
    // For Kotlin projects
    kotlinOptions {
        jvmTarget = "1.8"
    }
}

Kotlin

android {
    compileOptions {
        sourceCompatibility = JavaVersion.VERSION_1_8
        targetCompatibility = JavaVersion.VERSION_1_8
    }
    // For Kotlin projects
    kotlinOptions {
        jvmTarget = "1.8"
    }
}

เพิ่มโค้ดต่อไปนี้ลงในไฟล์ build.gradle ของแต่ละโมดูลสำหรับแอป

Groovy

dependencies {
  // CameraX core library using the camera2 implementation
  def camerax_version = "1.7.0-alpha02"
  // The following line is optional, as the core library is included indirectly by camera-camera2
  implementation "androidx.camera:camera-core:${camerax_version}"
  implementation "androidx.camera:camera-camera2:${camerax_version}"
  // If you want to additionally use the CameraX Lifecycle library
  implementation "androidx.camera:camera-lifecycle:${camerax_version}"
  // If you want to additionally use the CameraX VideoCapture library
  implementation "androidx.camera:camera-video:${camerax_version}"
  // If you want to additionally use the CameraX View class
  implementation "androidx.camera:camera-view:${camerax_version}"
  // If you want to additionally add CameraX ML Kit Vision Integration
  implementation "androidx.camera:camera-mlkit-vision:${camerax_version}"
  // If you want to additionally use the CameraX Extensions library
  implementation "androidx.camera:camera-extensions:${camerax_version}"
}

Kotlin

dependencies {
    // CameraX core library using the camera2 implementation
    val camerax_version = "1.7.0-alpha02"
    // The following line is optional, as the core library is included indirectly by camera-camera2
    implementation("androidx.camera:camera-core:${camerax_version}")
    implementation("androidx.camera:camera-camera2:${camerax_version}")
    // If you want to additionally use the CameraX Lifecycle library
    implementation("androidx.camera:camera-lifecycle:${camerax_version}")
    // If you want to additionally use the CameraX VideoCapture library
    implementation("androidx.camera:camera-video:${camerax_version}")
    // If you want to additionally use the CameraX View class
    implementation("androidx.camera:camera-view:${camerax_version}")
    // If you want to additionally add CameraX ML Kit Vision Integration
    implementation("androidx.camera:camera-mlkit-vision:${camerax_version}")
    // If you want to additionally use the CameraX Extensions library
    implementation("androidx.camera:camera-extensions:${camerax_version}")
}

ดูข้อมูลเพิ่มเติมเกี่ยวกับการกำหนดค่าแอปให้เป็นไปตามข้อกำหนดเหล่านี้ได้ที่การประกาศ การอ้างอิง

ความสามารถในการทำงานร่วมกันของ CameraX กับ Camera2

CameraX สร้างขึ้นบน Camera2 และแสดงวิธีอ่านและแม้กระทั่งเขียนพร็อพเพอร์ตี้ใน Camera2 โปรดดูรายละเอียดทั้งหมดในแพ็กเกจ Interop

ดูข้อมูลเพิ่มเติมเกี่ยวกับวิธีที่ CameraX กำหนดค่าพร็อพเพอร์ตี้ Camera2 ได้โดยใช้ Camera2CameraInfo เพื่ออ่านCameraCharacteristics ที่เกี่ยวข้อง นอกจากนี้ คุณยังเลือกเขียนพร็อพเพอร์ตี้ Camera2 ที่เกี่ยวข้องในเส้นทางใดเส้นทางหนึ่งต่อไปนี้ได้ด้วย

  • ใช้ Camera2CameraControl ซึ่งช่วยให้คุณตั้งค่าพร็อพเพอร์ตี้ในCaptureRequestพื้นฐาน เช่น โหมดโฟกัสอัตโนมัติ

  • ขยาย UseCase ของ CameraX ด้วย Camera2Interop.Extender ซึ่งช่วยให้คุณตั้งค่าพร็อพเพอร์ตี้ใน CaptureRequest ได้เช่นเดียวกับ Camera2CameraControl นอกจากนี้ ยังช่วยให้คุณควบคุมเพิ่มเติมได้ เช่น การตั้งค่ากรณีการใช้งานสตรีมเพื่อ เพิ่มประสิทธิภาพกล้องสำหรับสถานการณ์การใช้งานของคุณ ดูข้อมูลได้ที่ใช้ Use Case ของสตรีมเพื่อประสิทธิภาพที่ดีขึ้น

ตัวอย่างโค้ดต่อไปนี้ใช้ Use Case ของสตรีมเพื่อเพิ่มประสิทธิภาพสำหรับการวิดีโอคอล ใช้ Camera2CameraInfo เพื่อดึงข้อมูลว่ากรณีการใช้งานสตรีมวิดีโอคอลพร้อมใช้งานหรือไม่ จากนั้นใช้ Camera2Interop.Extender เพื่อตั้งค่ากรณีการใช้งานสตรีมพื้นฐาน

Kotlin

// Set underlying Camera2 stream use case to optimize for video calls.

val videoCallStreamId =
    CameraMetadata.SCALER_AVAILABLE_STREAM_USE_CASES_VIDEO_CALL.toLong()

// Check available CameraInfos to find the first one that supports
// the video call stream use case.
val frontCameraInfo = cameraProvider.getAvailableCameraInfos()
    .first { cameraInfo ->
        val isVideoCallStreamingSupported = Camera2CameraInfo.from(cameraInfo)
            .getCameraCharacteristic(
                CameraCharacteristics.SCALER_AVAILABLE_STREAM_USE_CASES
            )?.contains(videoCallStreamId)
        val isFrontFacing = (cameraInfo.getLensFacing() == 
                             CameraSelector.LENS_FACING_FRONT)
        (isVideoCallStreamingSupported == true) && isFrontFacing
    }

val cameraSelector = frontCameraInfo.cameraSelector

// Start with a Preview Builder.
val previewBuilder = Preview.Builder()
    .setTargetAspectRatio(screenAspectRatio)
    .setTargetRotation(rotation)

// Use Camera2Interop.Extender to set the video call stream use case.
Camera2Interop.Extender(previewBuilder).setStreamUseCase(videoCallStreamId)

// Bind the Preview UseCase and the corresponding CameraSelector.
val preview = previewBuilder.build()
camera = cameraProvider.bindToLifecycle(this, cameraSelector, preview)

Java

// Set underlying Camera2 stream use case to optimize for video calls.

Long videoCallStreamId =
    CameraMetadata.SCALER_AVAILABLE_STREAM_USE_CASES_VIDEO_CALL.toLong();

// Check available CameraInfos to find the first one that supports
// the video call stream use case.
List<CameraInfo> cameraInfos = cameraProvider.getAvailableCameraInfos();
CameraInfo frontCameraInfo = null;
for (cameraInfo in cameraInfos) {
    Long[] availableStreamUseCases = Camera2CameraInfo.from(cameraInfo)
        .getCameraCharacteristic(
            CameraCharacteristics.SCALER_AVAILABLE_STREAM_USE_CASES
        );
    boolean isVideoCallStreamingSupported = Arrays.List(availableStreamUseCases)
                .contains(videoCallStreamId);
    boolean isFrontFacing = (cameraInfo.getLensFacing() ==
                             CameraSelector.LENS_FACING_FRONT);

    if (isVideoCallStreamingSupported && isFrontFacing) {
        frontCameraInfo = cameraInfo;
    }
}

if (frontCameraInfo == null) {
    // Handle case where video call streaming is not supported.
}

CameraSelector cameraSelector = frontCameraInfo.getCameraSelector();

// Start with a Preview Builder.
Preview.Builder previewBuilder = Preview.Builder()
    .setTargetAspectRatio(screenAspectRatio)
    .setTargetRotation(rotation);

// Use Camera2Interop.Extender to set the video call stream use case.
Camera2Interop.Extender(previewBuilder).setStreamUseCase(videoCallStreamId);

// Bind the Preview UseCase and the corresponding CameraSelector.
Preview preview = previewBuilder.build()
Camera camera = cameraProvider.bindToLifecycle(this, cameraSelector, preview)

แหล่งข้อมูลเพิ่มเติม

ดูข้อมูลเพิ่มเติมเกี่ยวกับ CameraX ได้จากแหล่งข้อมูลเพิ่มเติมต่อไปนี้

Codelab

  • เริ่มต้นใช้งาน CameraX
  • ตัวอย่างโค้ด

  • ตัวอย่างแอป CameraX