בדף הזה נסביר על הארכיטקטורה של CameraX, כולל המבנה שלה, איך לעבוד עם ה-API, איך לעבוד עם מחזורי חיים ואיך לשלב תרחישים לדוגמה.
המבנה של CameraX
תוכלו להשתמש ב- CameraX כדי להתממשק עם מצלמת המכשיר באמצעות מהפשטה שנקראת 'תרחיש לדוגמה'. אלה התרחישים לדוגמה שאפשר להשתמש בהם:
- Preview: מאפשרת להשתמש בפלטפורמה להצגת תצוגה מקדימה, כמו
PreviewView
. - ניתוח תמונות: מספק מאגרים (buffers) שזמינים למעבד לצורך ניתוח, למשל לצורך למידת מכונה.
- צילום תמונה: צילום ושמירה של תמונה.
- צילום וידאו: צילום וידאו ואודיו באמצעות
VideoCapture
אפשר לשלב תרחישים לדוגמה ולהפעיל אותם בו-זמנית. לדוגמה, אפליקציה יכולה לאפשר למשתמש לראות את התמונה שמוצגת במצלמה באמצעות תרחיש לדוגמה של תצוגה מקדימה, לכלול תרחיש לדוגמה של ניתוח תמונות כדי לקבוע אם האנשים בתמונה מחייכים, ולכלול תרחיש לדוגמה של צילום תמונות כדי לצלם תמונה ברגע שהאנשים מחייכים.
מודל API
כדי לעבוד עם הספרייה, עליך לציין את הדברים הבאים:
- תרחיש לדוגמה עם אפשרויות תצורה.
- מה לעשות עם נתוני פלט על ידי צירוף מאזינים.
- התהליך המיועד, למשל מתי להפעיל את המצלמות ומתי להפיק נתונים, קישור של התרחיש לדוגמה לארכיטקטורת Android מחזורי חיים.
יש שתי דרכים לכתוב באפליקציית CameraX:
CameraController
(נהדר אם
הדרך הפשוטה ביותר להשתמש ב- CameraX)
CameraProvider
(מעולה אם
יותר גמישות).
שלט רחוק למצלמה
CameraController
מספק את רוב הפונקציונליות של הליבה של CameraX בכיתה אחת. נדרש מעט קוד הגדרה, והוא מטפל באופן אוטומטי בהפעלת המצלמה, בניהול תרחישי שימוש, ברוטציית היעד, בהקשה לצורך התמקדות, בתנועת הצמדה לצורך הגדלה ועוד. מחלקת הבטון שמשתרעת על ידי 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
, אפשר לעיין בדוגמה לסורק קודי QR או בסרטון בנושא העקרונות הבסיסיים של CameraController
.
CameraProvider
עדיין קל להשתמש ב-CameraProvider
, אבל מפַתח האפליקציה מטפל
יותר הגדרות, יש יותר הזדמנויות להתאים אישית את ההגדרות,
כמו הפעלת סיבוב תמונה של פלט או הגדרת פורמט פלט תמונה
ImageAnalysis
. אפשר גם להשתמש ב-Surface
בהתאמה אישית לתצוגה המקדימה של המצלמה, כדי לקבל גמישות רבה יותר. לעומת זאת, ב-CameraController צריך להשתמש ב-PreviewView
. שימוש בקוד Surface
הקיים יכול להיות שימושי
שכבר מוגדר כקלט בחלקים אחרים של האפליקציה.
מגדירים תרחישים לדוגמה באמצעות methods של set()
ומסיימים אותם באמצעות build()
. כל אובייקט של תרחיש לדוגמה מספק קבוצה של ממשקי API ספציפיים לתרחיש לדוגמה. עבור
למשל, התרחיש לדוגמה של צילום תמונה מספק הפעלת method 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 לתרחישים לדוגמה מספקים קריאות ל-method וקריאות חזרה (callbacks) כדי לעקוב אחרי ההתקדמות.
כמו שמוסבר בקטע שילוב תרחישים לדוגמה, אפשר לקשר כמה תמהילים במחזור חיים אחד. אם האפליקציה שלכם צריכה לתמוך בתרחישים לדוגמה שלא ניתן לשלב, תוכלו לבצע אחת מהפעולות הבאות:
- לקבץ תרחישים לדוגמה תואמים ליותר מקטע אחד, ואז לעבור בין קטעים
- יצירת רכיב במחזור חיים מותאם אישית ושימוש בו כדי לשלוט במצלמה באופן ידני מחזור חיים
אם מפרידים בין התרחישים לדוגמה של התצוגה והמצלמה הבעלים של מחזור החיים (לדוגמה:
אם משתמשים במחזור חיים מותאם אישית או בשמירה
מקטע), לאחר מכן
חייב לוודא שכל התרחישים לדוגמה לא מוצמדים ל- CameraX באמצעות
ProcessCameraProvider.unbindAll()
או על ידי ביטול הקישור של כל תרחיש לדוגמה בנפרד. לחלופין, כשמקשרים תרחישים לדוגמה למחזור חיים, אפשר לאפשר ל-CameraX לנהל את פתיחת סשן הצילום ואת סגירתו, וגם לבטל את הקישור של התרחישים לדוגמה.
אם כל הפונקציונליות של המצלמה תואמת למחזור החיים של
שמודע למחזור חיים, כמו
AppCompatActivity
או
מקטע AppCompat
, ולאחר מכן שימוש במחזור החיים של הרכיב הזה במהלך הקישור
את כל התרחישים לדוגמה הרצויים יבטיחו שהפונקציונליות של המצלמה תהיה מוכנה
כשהרכיב המודע למחזור החיים פעיל ומושליך באופן בטוח,
וצריכת משאבים כלשהי, אחרת.
LifecycleOwners בהתאמה אישית
במקרים מתקדמים, אפשר ליצור LifecycleOwner
בהתאמה אישית כדי לאפשר לאפליקציה לשלוט באופן מפורש במחזור החיים של הסשן ב-CameraX, במקום לקשר אותו ל-LifecycleOwner
רגיל של Android.
דוגמת הקוד הבאה מראה איך ליצור בעלים פשוט של מחזור חיים בהתאמה אישית:
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
, האפליקציה יכולה למקם את מעברי המצב בנקודות הרצויות בקוד שלה. כדי לקבל מידע נוסף על הטמעת הפונקציונליות הזו באפליקציה,
מידע נוסף זמין בקטע יישום של
בעלים של מחזור חיים.
תרחישים לדוגמה בו-זמנית
תרחישים לדוגמה יכולים לפעול בו-זמנית. אפשר לקשר תרחישים לדוגמה לסירוגין למחזור חיים, אבל עדיף לקשר את כל התרחישים לדוגמה באמצעות קריאה אחת ל-CameraProcessProvider.bindToLifecycle()
. מידע נוסף על שיטות מומלצות לשינויים בהגדרות זמין במאמר טיפול בשינויים בהגדרות.
בדוגמת הקוד הבאה, האפליקציה מציינת את שני התרחישים לדוגמה שיש ליצור והם פועלים בו-זמנית. הוא גם מציין את מחזור החיים שבו יש להשתמש בשני תרחישים לדוגמה, כך שהם יתחילו ויפסיקו לפעול בהתאם למחזור החיים.
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
. בנוסף,
- כל תרחיש לדוגמה יכול לפעול בפני עצמו. לדוגמה, אפליקציה יכולה להקליט סרטונים בלי להשתמש בתצוגה מקדימה.
- כשהתוספים מופעלים, רק
ImageCapture
וPreview
להבטיח שהשילוב יעבוד. בהתאם להטמעת ה-OEM, ייתכן שלא תהיה אפשרות להוסיף גםImageAnalysis
; תוספים לא יכולים בתרחיש לדוגמה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 יש את דרישות הגרסה המינימליות הבאות:
- Android API רמת 21
- רכיבי הארכיטקטורה של Android 1.1.1
לפעילויות שמתבססות על מחזור חיים, משתמשים ב-FragmentActivity
או ב-AppCompatActivity
.
הצהרת יחסי תלות
כדי להוסיף תלות ב- 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.5.0-alpha01" // 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-alpha01" // 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 ו- CameraX חושף דרכים לקרוא ואפילו לכתוב בהטמעה של Camera2. פרטים מלאים זמינים בחבילת ה-Interop.
לקבלת מידע נוסף על האופן שבו המצלמהX הגדירה מאפייני Camera2, השתמשו ב-
Camera2CameraInfo
כדי לקרוא את CameraCharacteristics
הבסיסי. אפשר גם לכתוב את המאפיינים הבסיסיים של Camera2 באחת משתי הדרכים הבאות:
משתמשים ב-
Camera2CameraControl
, שמאפשר להגדיר מאפיינים ב-CaptureRequest
הבסיסי, כמו מצב המיקוד האוטומטי.הרחבת
UseCase
של CameraX באמצעותCamera2Interop.Extender
. כך תוכלו להגדיר מאפיינים ב-CaptureRequest, בדיוק כמו ב-Camera2CameraControl
. הוא גם מספק כמה אמצעי בקרה נוספים, כמו הגדרת התרחיש לדוגמה של השידור לבצע אופטימיזציה של המצלמה לתרחיש השימוש שלכם. למידע נוסף, ראו שימוש בתרחישים לדוגמה של עדכוני תוכן לשיפור הביצועים או של ביצועים.
בדוגמת הקוד הבאה נעשה שימוש בתרחישי שימוש של סטרימינג כדי לבצע אופטימיזציה לשיחות וידאו.
משתמשים ב-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
דוגמת קוד