ארכיטקטורת CameraX

בדף הזה מוסבר על הארכיטקטורה של CameraX, כולל המבנה שלה, איך עובדים עם ה-API, איך עובדים עם מחזורי חיים ואיך משלבים תרחישי שימוש.

המבנה של CameraX

אפשר להשתמש ב-CameraX כדי ליצור אינטראקציה עם המצלמה של המכשיר באמצעות הפשטה שנקראת תרחיש לדוגמה. אלה תרחישי השימוש הזמינים:

  • תצוגה מקדימה: מקבלת משטח להצגת תצוגה מקדימה, כמו PreviewView.
  • ניתוח תמונות: מספק מאגרי נתונים (באפרים) שנגישים ל-CPU לצורך ניתוח, למשל ללמידת מכונה.
  • צילום תמונה: צילום ושמירה של תמונה.
  • הקלטת וידאו: הקלטת וידאו ואודיו באמצעות VideoCapture

אפשר לשלב בין תרחישים לדוגמה ולהפעיל אותם בו-זמנית. לדוגמה, אפליקציה יכולה לאפשר למשתמש לצפות בתמונה שהמצלמה רואה באמצעות תרחיש שימוש בתצוגה מקדימה, לכלול תרחיש שימוש בניתוח תמונה שקובע אם האנשים בתמונה מחייכים, ולכלול תרחיש שימוש בצילום תמונה כדי לצלם תמונה כשהם מחייכים.

מודל API

כדי לעבוד עם הספרייה, צריך לציין את הדברים הבאים:

  • תרחיש השימוש הרצוי עם אפשרויות ההגדרה.
  • מה עושים עם נתוני הפלט על ידי צירוף של רכיבי Listener.
  • הזרימה המיועדת, למשל מתי להפעיל מצלמות ומתי ליצור נתונים, על ידי קישור תרחיש השימוש אל מחזורי החיים של ארכיטקטורת Android.

יש 2 דרכים לכתוב אפליקציית CameraX: ‏ CameraController (הדרך הפשוטה ביותר להשתמש ב-CameraX) או CameraProvider (אם אתם צריכים גמישות רבה יותר).

CameraController

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 הקיים יכול להיות שימושי אם הוא כבר משמש כקלט בחלקים אחרים של האפליקציה.

מגדירים תרחישי שימוש באמצעות שיטות 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 של תרחישי שימוש מספקים קריאות לשיטות וקריאות חוזרות (callbacks) כדי לעקוב אחרי ההתקדמות.

כמו שמוסבר בתרחישים לדוגמה לשימוש בפעולת השילוב, אפשר לקשר כמה שילובים של תרחישים למחזור חיים יחיד. אם האפליקציה שלכם צריכה לתמוך בתרחישי שימוש שלא ניתן לשלב, אתם יכולים לבצע אחת מהפעולות הבאות:

  • לקבץ תרחישי שימוש תואמים לכמה קטעים ואז לעבור בין הקטעים
  • יצירת רכיב מותאם אישית של מחזור החיים ושימוש בו כדי לשלוט ידנית במחזור החיים של המצלמה

אם מפרידים את הבעלות על מחזור החיים של תצוגה ושל תרחישי שימוש במצלמה (לדוגמה, אם משתמשים במחזור חיים בהתאמה אישית או ב-retain fragment), צריך לוודא שכל תרחישי השימוש לא קשורים ל-CameraX באמצעות ProcessCameraProvider.unbindAll() או באמצעות ביטול הקישור של כל תרחיש שימוש בנפרד. לחלופין, כשמקשרים תרחישי שימוש למחזור חיים, אפשר לאפשר ל-CameraX לנהל את הפתיחה והסגירה של סשן הצילום ואת ביטול הקישור של תרחישי השימוש.

אם כל הפונקציונליות של המצלמה תואמת למחזור החיים של רכיב יחיד שמודע למחזור החיים, כמו AppCompatActivity או fragment של AppCompat, שימוש במחזור החיים של הרכיב הזה בזמן הקישור של כל תרחישי השימוש הרצויים יבטיח שהפונקציונליות של המצלמה תהיה מוכנה כשהרכיב שמודע למחזור החיים פעיל, ושהיא תבוטל בצורה בטוחה ולא תצרוך משאבים.

רכיבי Custom 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(). מידע נוסף על שיטות מומלצות לשינויים בהגדרות זמין במאמר טיפול בשינויים בהגדרות.

בדוגמת הקוד הבאה, האפליקציה מציינת את שני תרחישי השימוש שייווצרו ויפעלו בו-זמנית. היא גם מציינת את מחזור החיים שבו יש להשתמש בשני תרחישי השימוש, כך ששניהם יתחילו ויסתיימו בהתאם למחזור החיים.

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 מובטח שיפעל. יכול להיות שלא תהיה אפשרות להוסיף גם את ImageAnalysis, בהתאם להטמעה של יצרן הציוד המקורי. אי אפשר להפעיל תוספים לתרחיש השימוש של 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:

  • רמת API‏ 21 ב-Android
  • רכיבי ארכיטקטורה של 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-beta01"
  // 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-beta01"
    // 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. פרטים מלאים זמינים במאמר בנושא חבילת שילוב עם מערכות אחרות.

למידע נוסף על האופן שבו CameraX הגדירה את המאפיינים של Camera2, אפשר להשתמש ב-Camera2CameraInfo כדי לקרוא את CameraCharacteristics הבסיסי. אפשר גם לבחור לכתוב את מאפייני Camera2 הבסיסיים באחת משתי הדרכים הבאות:

בדוגמת הקוד הבאה נעשה שימוש בתרחישי שימוש בסטרימינג כדי לבצע אופטימיזציה לשיחת וידאו. משתמשים ב-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