CameraX mimarisi

Bu sayfada, CameraX'in yapısı, API ile çalışma, yaşam döngüleriyle çalışma ve kullanım alanlarını birleştirme gibi konular ele alınmaktadır.

CameraX yapısı

Kullanım alanı adı verilen bir soyutlama aracılığıyla bir cihazın kamerasıyla arayüz oluşturmak için CameraX'i kullanabilirsiniz. Aşağıdaki kullanım alanları mevcuttur:

  • Önizleme: Önizlemenin gösterileceği bir yüzeyi (ör. PreviewView) kabul eder.
  • Görüntü analizi: Analiz için CPU'ya erişilebilen arabellekler sağlar (ör. makine öğrenimi için).
  • Görüntü yakalama: Fotoğraf çeker ve kaydeder.
  • Video yakalama: VideoCapture ile video ve ses kaydı yapın

Kullanım alanları birleştirilebilir ve aynı anda etkin olabilir. Örneğin, bir uygulamada önizleme kullanım alanı kullanılarak kullanıcının kameranın gördüğü görüntüyü görüntülemesine izin verilebilir, fotoğraftaki kişilerin gülümseyip gülümsemediğini belirleyen bir resim analizi kullanım alanı bulunabilir ve gülümsedikleri anda fotoğraf çekmek için bir resim yakalama kullanım alanı eklenebilir.

API modeli

Kitaplıkla çalışmak için aşağıdakileri belirtirsiniz:

  • Yapılandırma seçenekleriyle istenen kullanım alanı.
  • Dinleyici ekleyerek çıkış verileriyle ne yapmalı?
  • Kullanım alanını Android mimari yaşam döngülerine bağlayarak kameraların ne zaman etkinleştirileceği ve ne zaman veri üretileceği gibi amaçlanan akış.

CameraX uygulaması yazmanın 2 yolu vardır: CameraController (CameraX'i kullanmanın en basit yolunu istiyorsanız idealdir) veya CameraProvider (daha fazla esnekliğe ihtiyacınız varsa idealdir).

CameraController

CameraController, CameraX temel işlevlerinin çoğunu tek bir sınıfta sağlar. Az miktarda kurulum kodu gerektirir ve kamerayı başlatma, kullanım alanı yönetimi, hedef döndürme, dokunarak odaklama, iki parmak ucunu yakınlaştırma/uzaklaştırma ve daha fazlasını otomatik olarak yönetir. CameraController sınıfını genişleten somut sınıf 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);

CameraController için varsayılan UseCase'ler Preview, ImageCapture ve ImageAnalysis'tir. ImageCapture veya ImageAnalysis'ü kapatmak ya da VideoCapture'yi açmak için setEnabledUseCases() yöntemini kullanın.

CameraController'ün diğer kullanımları için QR kodu tarayıcı örneğine veya CameraController ile ilgili temel bilgiler videosuna göz atın.

CameraProvider

CameraProvider'ler yine de kullanımı kolaydır ancak kurulumun büyük bir kısmı uygulama geliştirici tarafından yapıldığından, yapılandırmanızı özelleştirmek için daha fazla fırsat vardır (ör. çıkış resminin döndürülmesini etkinleştirme veya ImageAnalysis'te çıkış resmi biçimini ayarlama). Kamera önizlemesi için özel bir Surface de kullanabilirsiniz. Bu, daha fazla esneklik sağlar. CameraController ile ise bir PreviewView kullanmanız gerekir. Mevcut Surface kodunuz, uygulamanızın diğer bölümlerinde zaten giriş olarak kullanılıyorsa faydalı olabilir.

Kullanım alanlarını set() yöntemlerini kullanarak yapılandırır ve build() yöntemiyle sonlandırırsınız. Her kullanım alanı nesnesi, kullanım alanına özel bir API grubu sağlar. Örneğin, resim yakalama kullanım alanı bir takePicture() yöntem çağrısı sağlar.

Uygulama, onResume() ve onPause()'a belirli başlatma ve durdurma yöntemi çağrıları yerleştirmek yerine cameraProvider.bindToLifecycle() kullanarak kamerayı ilişkilendirecek bir yaşam döngüsü belirtir. Bu yaşam döngüsü daha sonra CameraX'e kamera yakalama oturumunun ne zaman yapılandırılacağını bildirir ve kamera durumunun yaşam döngüsü geçişleriyle eşleşecek şekilde uygun şekilde değişmesini sağlar.

Her kullanım alanı için uygulama adımları Önizleme uygulama, Resimleri analiz etme, Resim yakalama ve Video yakalama başlıklı makalelere göz atın.

Önizleme kullanım alanı, görüntüleme için Surface ile etkileşim kurar. Uygulamalar, aşağıdaki kodu kullanarak yapılandırma seçenekleriyle kullanım alanını oluşturur:

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();

Daha fazla örnek kod için resmi CameraX örnek uygulamasına bakın.

CameraX Yaşam Döngüleri

CameraX, kameranın ne zaman açılacağını, ne zaman çekim oturumu oluşturulacağını ve ne zaman durdurulup kapatılacağını belirlemek için bir yaşam döngüsü izler. Kullanım alanı API'leri, ilerlemeyi izlemek için yöntem çağrıları ve geri çağırma işlevleri sağlar.

Kullanım alanlarını birleştirme bölümünde açıklandığı gibi, bazı kullanım alanı karışımlarını tek bir yaşam döngüsüne bağlayabilirsiniz. Uygulamanızın birleştirilemeyen kullanım alanlarını desteklemesi gerektiğinde aşağıdakilerden birini yapabilirsiniz:

  • Uyumlu kullanım alanlarını birden fazla parça halinde gruplandırabilir ve ardından parçalar arasında geçiş yapabilirsiniz.
  • Özel bir yaşam döngüsü bileşeni oluşturun ve kamera yaşam döngüsünü manuel olarak kontrol etmek için kullanın

Görüntüleme ve kamera kullanım alanlarınızın yaşam döngüsü sahiplerini ayırırsanız (ör. özel yaşam döngüsü veya retain fragment kullanıyorsanız) ProcessCameraProvider.unbindAll() kullanarak veya her kullanım alanının bağlamasını tek tek kaldırarak tüm kullanım alanlarının CameraX'ten ayrıldığından emin olmanız gerekir. Alternatif olarak, kullanım alanlarını bir yaşam döngüsüne bağladığınızda CameraX'in, yakalama oturumunu açıp kapatmasını ve kullanım alanlarını bağlamayı kaldırmasını sağlayabilirsiniz.

Kamera işlevlerinizin tümü, AppCompatActivity veya AppCompat fragmanı gibi yaşam döngüsü bilincine sahip tek bir bileşenin yaşam döngüsüne karşılık geliyorsa, istenen tüm kullanım alanlarını bağlarken bu bileşenin yaşam döngüsünü kullanmak, yaşam döngüsü bilincine sahip bileşen etkin olduğunda kamera işlevinin hazır olmasını ve aksi takdirde herhangi bir kaynak tüketmeden güvenli bir şekilde kaldırılmasını sağlar.

Özel LifecycleOwner'lar

Gelişmiş durumlarda, uygulamanızın standart bir Android LifecycleOwner'a bağlamak yerine CameraX oturum yaşam döngüsünü açıkça kontrol etmesini sağlamak için özel bir LifecycleOwner oluşturabilirsiniz.

Aşağıdaki kod örneğinde, basit bir özel LifecycleOwner'ın nasıl oluşturulacağı gösterilmektedir:

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;
    }
}

Bu LifecycleOwner sayesinde uygulamanız, kodunun istenen noktalarına durum geçişleri yerleştirebilir. Bu işlevi uygulamanızda uygulama hakkında daha fazla bilgi için Özel LifecycleOwner uygulama başlıklı makaleyi inceleyin.

Eşzamanlı kullanım alanları

Kullanım alanları aynı anda çalışabilir. Kullanım alanları bir yaşam döngüsüne sırayla bağlanabilir ancak tüm kullanım alanlarını CameraProcessProvider.bindToLifecycle() çağrısıyla bağlamak daha iyidir. Yapılandırma değişiklikleriyle ilgili en iyi uygulamalar hakkında daha fazla bilgi için Yapılandırma değişikliklerini yönetme başlıklı makaleyi inceleyin.

Aşağıdaki kod örneğinde, uygulama oluşturulacak ve aynı anda çalıştırılacak iki kullanım alanını belirtir. Ayrıca, her iki kullanım alanı için de kullanılacak yaşam döngüsünü belirtir. Böylece her ikisi de yaşam döngüsüne göre başlatılır ve durdurulur.

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 ve ImageCapture için aynı anda birer örneğin kullanılmasına olanak tanır. Ayrıca,

  • Her kullanım alanı kendi başına çalışabilir. Örneğin, bir uygulama önizlemeyi kullanmadan video kaydedebilir.
  • Uzantılar etkinleştirildiğinde yalnızca ImageCapture ve Preview kombinasyonunun çalışacağı garanti edilir. OEM uygulamasına bağlı olarak ImageAnalysis'ü de eklemek mümkün olmayabilir; uzantılar VideoCapture kullanım alanı için etkinleştirilemez. Ayrıntılar için Uzantı referans dokümanlarını inceleyin.
  • Kameranın kapasitesine bağlı olarak bazı kameralar bu kombinasyonu daha düşük çözünürlük modlarında destekleyebilir ancak bazı yüksek çözünürlüklerde aynı kombinasyonu desteklemeyebilir.
  • Kamera donanım düzeyi FULL veya daha düşük olan cihazlarda Preview, VideoCapture ve ImageCapture veya ImageAnalysis seçeneklerinin birlikte kullanılması, CameraX'in kameranın PRIV yayınını Preview ve VideoCapture için kopyalamasını zorunlu kılabilir. Akış paylaşımı olarak adlandırılan bu kopyalama, bu özelliklerin eş zamanlı kullanımına olanak tanır ancak işleme taleplerinin artması pahasına gelir. Bu nedenle, biraz daha yüksek gecikme süresi ve daha kısa pil ömrü yaşayabilirsiniz.

Desteklenen donanım düzeyi, Camera2CameraInfo adresinden alınabilir. Örneğin, aşağıdaki kodda varsayılan arka kameranın LEVEL_3 cihaz olup olmadığı kontrol edilir:

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;
}

İzinler

Uygulamanızın CAMERA iznine ihtiyacı vardır. Android 10 veya sonraki sürümleri çalıştıran cihazlar hariç olmak üzere, resimleri dosyalara kaydetmek için WRITE_EXTERNAL_STORAGE izni de gerekir.

Uygulamanızın izinlerini yapılandırma hakkında daha fazla bilgi için Uygulama İzinleri İsteme başlıklı makaleyi inceleyin.

Şartlar

CameraX'in minimum sürüm gereksinimleri şunlardır:

  • Android API düzeyi 21
  • Android Mimarisi Bileşenleri 1.1.1

Yaşam döngüsü bilincine sahip etkinlikler için FragmentActivity veya AppCompatActivity değerini kullanın.

Bağımlılıkları bildirme

CameraX bağımlılığı eklemek için projenize Google Maven kod deposunu eklemeniz gerekir.

Projenizin settings.gradle dosyasını açın ve aşağıdaki gibi google() deposunu ekleyin:

Groovy

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

Kotlin

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

Android bloğunun sonuna aşağıdakileri ekleyin:

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"
    }
}

Bir uygulamanın her modülünün build.gradle dosyasına aşağıdakileri ekleyin:

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}")
}

Uygulamanızı bu şartlara uygun olacak şekilde yapılandırma hakkında daha fazla bilgi için Bağımlılık beyanı başlıklı makaleyi inceleyin.

CameraX'in Camera2 ile birlikte çalışabilirliği

CameraX, Camera2'yi temel alır ve Camera2 uygulamasında özellikleri okumanın ve hatta yazmanın yollarını sunar. Tüm ayrıntılar için Interop paketine bakın.

CameraX'in Camera2 özelliklerini nasıl yapılandırdığı hakkında daha fazla bilgi edinmek için temel CameraCharacteristics dosyasını okumak üzere Camera2CameraInfo kullanın. Temel Camera2 özelliklerini aşağıdaki iki yoldan birinde yazmayı da seçebilirsiniz:

Aşağıdaki kod örneğinde, video görüşmesi için optimizasyon yapmak üzere yayın kullanım alanları kullanılmaktadır. Video görüşmesi akışı kullanım alanının kullanılabilir olup olmadığını almak için Camera2CameraInfo değerini kullanın. Ardından, temel akış kullanım alanını ayarlamak için Camera2Interop.Extender simgesini kullanı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)

Ek kaynaklar

CameraX hakkında daha fazla bilgi edinmek için aşağıdaki ek kaynaklara göz atın.

Codelab

  • CameraX'i kullanmaya başlama
  • Kod örneği

  • CameraX örnek uygulamaları