Trang này đề cập đến cấu trúc của CameraX, bao gồm cấu trúc, cách làm việc với API, cách làm việc với vòng đời và cách kết hợp các trường hợp sử dụng.
Cấu trúc CameraX
Bạn có thể sử dụng CameraX để giao tiếp với máy ảnh của thiết bị thông qua một giá trị trừu tượng được gọi là trường hợp sử dụng. Bạn có thể sử dụng các trường hợp sau:
- Xem trước: chấp nhận một nền tảng để hiển thị bản xem trước, chẳng hạn như
PreviewView
. - Phân tích hình ảnh: cung cấp vùng đệm mà CPU có thể truy cập để phân tích, chẳng hạn như cho công nghệ học máy.
- Chụp ảnh: chụp và lưu ảnh.
- Quay video: quay video và ghi âm bằng
VideoCapture
Các trường hợp sử dụng có thể được kết hợp và hoạt động đồng thời. Ví dụ: Một ứng dụng có thể cho phép người dùng xem hình ảnh mà máy ảnh thấy bằng trường hợp sử dụng xem trước, có trường hợp sử dụng phân tích hình ảnh xác định liệu những người trong ảnh có đang cười hay không và đưa vào một trường hợp sử dụng chụp ảnh để chụp khi mọi người đã sẵn sàng.
Mô hình API
Để làm việc với thư viện, bạn cần chỉ định những điều sau:
- Trường hợp sử dụng mong muốn với các tuỳ chọn cấu hình.
- Việc cần làm với dữ liệu đầu ra bằng cách đính kèm trình nghe.
- Quy trình dự kiến, chẳng hạn như thời điểm bật máy ảnh và thời điểm tạo dữ liệu, bằng cách liên kết trường hợp sử dụng với Vòng đời kiến trúc Android.
Có 2 cách để viết một ứng dụng CameraX: CameraController
(phù hợp nếu bạn muốn sử dụng CameraX theo cách đơn giản nhất) hoặc CameraProvider
(phù hợp nếu bạn cần tăng tính linh hoạt).
CameraController
CameraController
cung cấp hầu hết các chức năng cốt lõi của CameraX trong một lớp. Lớp này yêu cầu ít mã thiết lập và tự động xử lý việc khởi chạy máy ảnh, quản lý trường hợp sử dụng, xoay đích, nhấn để lấy nét, chụm để thu phóng và nhiều tác vụ khác. Lớp cụ thể giúp mở rộng CameraController
là 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
mặc định cho CameraController
là Preview
, ImageCapture
và ImageAnalysis
. Để tắt ImageCapture
hoặc ImageAnalysis
hay để bật VideoCapture
, hãy dùng phương thức setEnabledUseCases()
.
Để biết thêm về cách sử dụng CameraController
, hãy xem mẫu trình quét mã QR hoặc video kiến thức cơ bản về CameraController
.
CameraProvider
CameraProvider
vẫn dễ sử dụng, nhưng vì nhà phát triển ứng dụng xử lý nhiều vấn đề hơn trong khâu thiết lập, nên khả năng tuỳ chỉnh cấu hình sẽ lớn hơn, chẳng hạn như bật chế độ xoay hình ảnh đầu ra hoặc đặt định dạng hình ảnh đầu ra trong ImageAnalysis
. Bạn cũng có thể dùng Surface
tuỳ chỉnh cho trường hợp xem trước máy ảnh nhằm tăng tính linh hoạt, còn đối với CameraController, bạn bắt buộc phải dùng PreviewView
. Việc dùng Surface
hiện có có thể hữu ích nếu đoạn mã này đã là dữ liệu đầu vào cho các phần khác của ứng dụng.
Bạn định cấu hình các trường hợp sử dụng bằng các phương thức set()
và hoàn tất các trường hợp sử dụng đó bằng phương thức build()
. Mỗi đối tượng trường hợp sử dụng cung cấp một tập hợp API dành riêng cho trường hợp sử dụng. Ví dụ: Trường hợp sử dụng chụp ảnh cung cấp lệnh gọi phương thức takePicture()
.
Thay vì thực hiện các lệnh gọi phương thức bắt đầu và dừng cụ thể trong onResume()
và onPause()
, ứng dụng này chỉ định vòng đời để liên kết máy ảnh bằng cách sử dụng cameraProvider.bindToLifecycle()
.
Sau đó, vòng đời thông báo cho CameraX về thời điểm cần định cấu hình phiên chụp ảnh và đảm bảo trạng thái của máy ảnh thay đổi phù hợp để khớp với các chuyển đổi vòng đời.
Để biết các bước triển khai cho từng trường hợp sử dụng, xem bài viết Triển khai bản xem trước, Phân tích hình ảnh, Chụp ảnh và Quay video
Trường hợp sử dụng xem trước tương tác với một Surface
để hiển thị. Ứng dụng tạo trường hợp sử dụng với các tuỳ chọn cấu hình bằng đoạn mã sau:
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();
Để xem thêm đoạn mã ví dụ, hãy đọc bài viết ứng dụng mẫu CameraX chính thức.
CameraX Lifecycle
CameraX theo dõi vòng đời để xác định thời điểm mở máy ảnh, thời điểm tạo phiên chụp, cũng như thời điểm dừng và tắt. API trường hợp sử dụng cung cấp các lệnh gọi phương thức và lệnh gọi lại để theo dõi tiến trình.
Như giải thích trong phần Kết hợp các trường hợp sử dụng, bạn có thể liên kết một số danh sách kết hợp các trường hợp sử dụng với một vòng đời duy nhất. Khi ứng dụng của bạn cần hỗ trợ các trường hợp sử dụng không thể kết hợp được, bạn có thể thực hiện một trong những thao tác sau:
- Nhóm các trường hợp sử dụng tương thích lại với nhau thành nhiều mảnh, sau đó chuyển đổi giữa các mảnh
- Tạo một thành phần trong vòng đời tuỳ chỉnh và sử dụng thành phần đó để điều khiển vòng đời của máy ảnh theo cách thủ công
Nếu bạn tách riêng các chủ sở hữu Lifecycle của trường hợp sử dụng xem và máy ảnh (ví dụ: nếu bạn sử dụng vòng đời tuỳ chỉnh hoặc mảnh giữ lại), bạn phải đảm bảo rằng tất cả các trường hợp sử dụng huỷ liên kết với CameraX bằng cách sử dụng ProcessCameraProvider.unbindAll()
hoặc bằng cách huỷ liên kết từng trường hợp sử dụng một. Ngoài ra, khi liên kết các trường hợp sử dụng với Lifecycle, bạn có thể cho phép CameraX quản lý việc mở và đóng phiên chụp và huỷ liên kết các trường hợp sử dụng.
Nếu tất cả chức năng của máy ảnh tương ứng với vòng đời của một thành phần nhận biết vòng đời duy nhất, chẳng hạn như AppCompatActivity
hoặc một mảnh AppCompat
, thì việc sử dụng vòng đời của thành phần đó khi liên kết tất cả các trường hợp sử dụng mong muốn sẽ đảm bảo rằng chức năng của máy ảnh đã sẵn sàng khi thành phần nhận biết vòng đời hoạt động và được xử lý một cách an toàn, không tốn bất kỳ tài nguyên nào.
LifecycleOwner tuỳ chỉnh
Đối với các trường hợp nâng cao, bạn có thể tạo một LifecycleOwner
tuỳ chỉnh để cho phép ứng dụng của bạn kiểm soát rõ ràng vòng đời phiên CameraX thay vì liên kết với LifecycleOwner
tiêu chuẩn của Android.
Đoạn mã mẫu sau đây trình bày cách tạo một LifecycleOwner tuỳ chỉnh đơn giản:
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; } }
Khi sử dụng LifecycleOwner
này, ứng dụng của bạn có thể đặt các lượt chuyển đổi trạng thái tại các điểm mong muốn trong mã nguồn. Để biết thêm thông tin về cách triển khai chức năng này trong ứng dụng của bạn, hãy xem phần Triển khai một LifecycleOwner tuỳ chỉnh.
Các trường hợp sử dụng đồng thời
Các trường hợp sử dụng có thể chạy đồng thời. Mặc dù các trường hợp sử dụng có thể được liên kết tuần tự với một vòng đời, nhưng bạn nên liên kết tất cả các trường hợp sử dụng bằng một lệnh gọi tới CameraProcessProvider.bindToLifecycle()
. Để biết thêm thông tin về các phương pháp hay nhất khi thay đổi cấu hình, xem phần Xử lý các thay đổi về cấu hình.
Trong đoạn mã mẫu sau, ứng dụng chỉ định hai trường hợp sử dụng cần được tạo và chạy đồng thời. Đoạn mã mẫu này cũng xác định vòng đời cần sử dụng cho cả hai trường hợp sử dụng, để cả hai đều bắt đầu và dừng theo vòng đời đó.
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 cho phép sử dụng đồng thời một thực thể của Preview
, VideoCapture
, ImageAnalysis
và ImageCapture
. Ngoài ra,
- Mỗi trường hợp sử dụng đều có thể tự hoạt động. Ví dụ: Một ứng dụng có thể quay video mà không cần sử dụng tính năng xem trước.
- Khi các tiện ích được bật, chỉ tổ hợp
ImageCapture
vàPreview
là đảm bảo hoạt động. Tuỳ thuộc vào cách triển khai của OEM (Nhà sản xuất thiết bị gốc), bạn cũng có thể không thêm đượcImageAnalysis
; không thể bật tiện ích cho trường hợp sử dụngVideoCapture
. Xem Tài liệu tham khảo về tiện ích để biết thông tin chi tiết. - Tuỳ thuộc vào tính năng của máy ảnh, một số máy ảnh có thể hỗ trợ tổ hợp ở các chế độ độ phân giải thấp nhưng không thể hỗ trợ sử dụng cùng tổ hợp đó ở độ phân giải cao.
- Trên các thiết bị có cấp độ phần cứng máy ảnh
FULL
trở xuống, việc kết hợpPreview
,VideoCapture
vàImageCapture
hoặcImageAnalysis
có thể buộc CameraX sao chép luồngPRIV
của máy ảnh choPreview
vàVideoCapture
. Việc sao chép này, được gọi là chia sẻ luồng, cho phép sử dụng đồng thời các tính năng này nhưng phải trả giá bằng việc tăng nhu cầu xử lý. Do đó, bạn có thể nhận thấy độ trễ cao hơn một chút và thời lượng pin giảm.
Bạn có thể truy xuất cấp độ phần cứng được hỗ trợ từ Camera2CameraInfo
. Ví dụ: Đoạn mã sau đây kiểm tra xem máy ảnh mặt sau mặc định có phải là thiết bị LEVEL_3
không:
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\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; }
Quyền
Ứng dụng của bạn sẽ cần được cấp quyền CAMERA
. Để lưu hình ảnh vào tệp, bạn cũng cần có quyền WRITE_EXTERNAL_STORAGE
, ngoại trừ trên các thiết bị chạy Android 10 trở lên.
Để biết thêm thông tin về cách định cấu hình quyền cho ứng dụng của bạn, đọc bài viết Yêu cầu quyền cho ứng dụng.
Yêu cầu
CameraX có các yêu cầu tối thiểu về phiên bản sau đây:
- Android API cấp 21
- Bộ thành phần cấu trúc Android 1.1.1
Đối với các hoạt động nhận biết vòng đời, sử dụng FragmentActivity
hoặc AppCompatActivity
.
Khai báo phần phụ thuộc
Để thêm một phần phụ thuộc trên CameraX, bạn phải thêm kho lưu trữ Google Maven vào dự án.
Mở tệp settings.gradle
cho dự án của bạn và thêm kho lưu trữ google()
như trong đoạn mã sau:
Groovy
dependencyResolutionManagement { repositoriesMode.set(RepositoriesMode.FAIL_ON_PROJECT_REPOS) repositories { google() mavenCentral() } }
Kotlin
dependencyResolutionManagement { repositoriesMode.set(RepositoriesMode.FAIL_ON_PROJECT_REPOS) repositories { google() mavenCentral() } }
Thêm đoạn mã sau vào cuối khối lệnh Android:
Groovy
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" } }
Thêm phần sau vào tệp build.gradle
của từng mô-đun cho một ứng dụng:
Groovy
dependencies { // CameraX core library using the camera2 implementation def camerax_version = "1.5.0-alpha03" // 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.5.0-alpha03" // 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}") }
Để biết thêm thông tin về cách định cấu hình ứng dụng của bạn nhằm tuân thủ các yêu cầu này, hãy xem bài viết Khai báo phần phụ thuộc.
Khả năng tương tác của CameraX với Camera2
CameraX được tạo dựa trên Camera2. CameraX cho biết các cách đọc và thậm chí là ghi các thuộc tính trong quá trình triển khai Camera2. Để biết toàn bộ thông tin chi tiết, hãy xem bài viết về Gói khả năng tương tác.
Để biết thêm thông tin về cách CameraX định cấu hình các thuộc tính của Camera2, hãy dùng Camera2CameraInfo
để đọc CameraCharacteristics
cơ bản. Bạn cũng có thể chọn ghi các thuộc tính của Camera2 cơ bản vào một trong hai đường dẫn sau:
Dùng
Camera2CameraControl
để đặt các thuộc tính trênCaptureRequest
cơ bản, chẳng hạn như chế độ tự động lấy nét.Mở rộng CameraX
UseCase
bằngCamera2Interop.Extender
. Thao tác này cho phép bạn đặt các thuộc tính trên CaptureRequest, giống nhưCamera2CameraControl
. Thao tác này cũng cung cấp cho bạn một số chế độ điều khiển bổ sung, chẳng hạn như đặt trường hợp sử dụng phát trực tuyến để tối ưu hoá máy ảnh cho trường hợp sử dụng của bạn. Để biết thông tin, hãy xem bài viết Dùng các trường hợp sử dụng phát trực tuyến để có hiệu suất tốt hơn.
Mã mẫu sau đây dùng các trường hợp sử dụng phát trực tuyến để tối ưu hoá cho một cuộc gọi video.
Dùng Camera2CameraInfo
để tìm nạp xem có trường hợp sử dụng truyền phát cuộc gọi video hay không. Sau đó, hãy dùng Camera2Interop.Extender
để đặt trường hợp sử dụng phát trực tuyến cơ bản.
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)
Tài nguyên khác
Để tìm hiểu thêm về CameraX, hãy tham khảo các tài liệu bổ sung sau đây.
Lớp học lập trình
Đoạn mã mẫu