หน้านี้ครอบคลุมสถาปัตยกรรมของ CameraX ซึ่งรวมถึงโครงสร้าง วิธีทำงานกับ API วิธีทำงานกับวงจร และวิธีรวม Use Case
โครงสร้าง CameraX
คุณสามารถใช้ CameraX เพื่อเชื่อมต่อกับกล้องของอุปกรณ์ผ่านนามธรรมที่เรียกว่า Use Case กรณีการใช้งานที่พร้อมใช้งานมีดังนี้
- Preview: ยอมรับแพลตฟอร์มสำหรับการแสดงตัวอย่าง เช่น
PreviewView - การวิเคราะห์รูปภาพ: มีบัฟเฟอร์ที่ CPU เข้าถึงได้สำหรับการวิเคราะห์ เช่น สำหรับแมชชีนเลิร์นนิง
- การจับภาพ: จับภาพและบันทึกรูปภาพ
- การจับภาพวิดีโอ: จับภาพวิดีโอและเสียงด้วย
VideoCapture
คุณสามารถรวม Use Case และใช้งานพร้อมกันได้ ตัวอย่างเช่น แอปสามารถให้ผู้ใช้ดูรูปภาพที่กล้องเห็นโดยใช้ Use Case ของตัวอย่าง มี Use Case ของการวิเคราะห์รูปภาพที่ระบุว่าผู้คนในรูปภาพยิ้มอยู่หรือไม่ และรวม 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 ที่มีอยู่อาจเป็นประโยชน์หากโค้ดดังกล่าวเป็นอินพุตไปยังส่วนอื่นๆ ของแอปอยู่แล้ว
คุณกำหนดค่ากรณีการใช้งานโดยใช้เมธอด set() และสรุปผลด้วยเมธอด build() ออบเจ็กต์กรณีการใช้งานแต่ละรายการจะมีชุด API เฉพาะสำหรับกรณีการใช้งาน ตัวอย่างเช่น กรณีการใช้งานการจับภาพจะมีการเรียกใช้เมธอด takePicture()
แทนที่แอปพลิเคชันจะวางการเรียกใช้เมธอดเริ่มต้นและหยุดที่เฉพาะเจาะจงใน onResume() และ onPause() แอปพลิเคชันจะระบุวงจรเพื่อเชื่อมโยงกล้องกับ cameraProvider.bindToLifecycle()
จากนั้นวงจรดังกล่าวจะแจ้งให้ CameraX ทราบว่าควรกำหนดค่าเซสชันการจับภาพของกล้องเมื่อใด และตรวจสอบว่าสถานะของกล้องเปลี่ยนแปลงอย่างเหมาะสมเพื่อให้สอดคล้องกับการเปลี่ยนผ่านของวงจร
ดูขั้นตอนการใช้งานสำหรับ Use Case แต่ละกรณีได้ที่ใช้ตัวอย่าง วิเคราะห์รูปภาพ Image Capture และจับภาพวิดีโอ
กรณีการใช้งานตัวอย่างจะโต้ตอบกับ Surface เพื่อแสดงผล แอปพลิเคชันจะสร้าง Use Case ที่มีตัวเลือกการกำหนดค่าโดยใช้โค้ดต่อไปนี้
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 ที่ไม่สามารถรวมกันได้ คุณสามารถทำอย่างใดอย่างหนึ่งต่อไปนี้
- จัดกลุ่มกรณีการใช้งานที่เข้ากันได้ไว้ด้วยกันในส่วนย่อยมากกว่า 1 ส่วน แล้วสลับไปมาระหว่างส่วนย่อยต่างๆ
- สร้างคอมโพเนนต์วงจรที่กำหนดเองและใช้เพื่อควบคุมวงจรของกล้องด้วยตนเอง
หากคุณแยก LifecycleOwner ของ Use Case ของมุมมองและกล้องออกจากกัน (เช่น หากคุณใช้ Lifecycle ที่กำหนดเองหรือ retain fragment) คุณต้องตรวจสอบว่า Use Case ทั้งหมดไม่ได้เชื่อมโยงกับ CameraX โดยใช้ ProcessCameraProvider.unbindAll() หรือโดยการยกเลิกการเชื่อมโยง Use Case แต่ละรายการแยกกัน หรือเมื่อคุณเชื่อมโยง Use Case กับวงจร คุณสามารถให้ CameraX จัดการการเปิดและปิดเซสชันการจับภาพและการยกเลิกการเชื่อมโยง Use Case ได้
หากฟังก์ชันการทำงานทั้งหมดของกล้องสอดคล้องกับวงจรของคอมโพเนนต์ที่รับรู้วงจรรายการเดียว เช่น 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() เพียงครั้งเดียวจะดีกว่า ดูข้อมูลเพิ่มเติมเกี่ยวกับแนวทางปฏิบัติแนะนำสำหรับการเปลี่ยนแปลงการกำหนดค่าได้ที่หัวข้อจัดการการเปลี่ยนแปลงการกำหนดค่า
ในตัวอย่างโค้ดต่อไปนี้ แอปจะระบุกรณีการใช้งาน 2 กรณีที่จะสร้างและเรียกใช้พร้อมกัน นอกจากนี้ยังระบุวงจรที่จะใช้สำหรับทั้ง 2 Use Case เพื่อให้ทั้ง 2 Use Case เริ่มต้นและหยุดตามวงจร
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 CaseVideoCaptureดูรายละเอียดได้ที่เอกสารอ้างอิงส่วนขยาย - กล้องบางตัวอาจรองรับชุดค่าผสมที่โหมดความละเอียดต่ำกว่า แต่ไม่รองรับชุดค่าผสมเดียวกันที่ความละเอียดสูงกว่าบางค่า ทั้งนี้ขึ้นอยู่กับความสามารถของกล้อง
- ในอุปกรณ์ที่มีระดับฮาร์ดแวร์กล้อง
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 มีข้อกำหนดเวอร์ชันขั้นต่ำดังต่อไปนี้
- Android API ระดับ 21
- คอมโพเนนต์สถาปัตยกรรมของ 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-rc01" // 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-rc01" // 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}") }
ดูข้อมูลเพิ่มเติมเกี่ยวกับการกำหนดค่าแอปให้เป็นไปตามข้อกำหนดเหล่านี้ได้ที่การประกาศทรัพยากร Dependency
ความสามารถในการทำงานร่วมกันของ CameraX กับ Camera2
CameraX สร้างขึ้นบน Camera2 และ CameraX แสดงวิธีอ่านและเขียนพร็อพเพอร์ตี้ในการใช้งาน Camera2 ดูรายละเอียดทั้งหมดได้ที่แพ็กเกจ Interop
ดูข้อมูลเพิ่มเติมเกี่ยวกับวิธีที่ CameraX กำหนดค่าพร็อพเพอร์ตี้ Camera2 โดยใช้ Camera2CameraInfo เพื่ออ่าน CameraCharacteristics ที่สำคัญ นอกจากนี้ คุณยังเลือกเขียนพร็อพเพอร์ตี้ Camera2 ที่สำคัญได้ด้วยวิธีใดวิธีหนึ่งจาก 2 วิธีต่อไปนี้
ใช้
Camera2CameraControlซึ่งช่วยให้คุณตั้งค่าพร็อพเพอร์ตี้ในCaptureRequestที่สำคัญได้ เช่น โหมดโฟกัสอัตโนมัติขยาย
UseCaseของ CameraX ด้วยCamera2Interop.Extenderซึ่งช่วยให้คุณตั้งค่าพร็อพเพอร์ตี้ใน CaptureRequest ได้เช่นเดียวกับCamera2CameraControlนอกจากนี้ ยังให้การควบคุมเพิ่มเติมบางอย่าง เช่น การตั้งค่า Use Case ของสตรีมเพื่อเพิ่มประสิทธิภาพกล้องสำหรับสถานการณ์การใช้งานของคุณ ดูข้อมูลเพิ่มเติมได้ที่ใช้ 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
ตัวอย่างโค้ด