CameraX mimarisi

Bu sayfada, yapısı, API ile çalışma, yaşam döngüleriyle çalışma ve kullanım alanlarının nasıl birleştirileceği de dahil olmak üzere CameraX mimarisi ele alınmaktadır.

CameraX yapısı

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

  • Önizleme: Önizleme görüntülemek için PreviewView gibi bir yüzeyi kabul eder.
  • Görüntü analizi: Makine öğrenimi gibi analizler için CPU tarafından erişilebilen arabellekler sağlar.
  • Resim çekme: Fotoğraf çeker ve kaydeder.
  • Video çekimi: VideoCapture ile video ve ses kaydedin

Kullanım alanları eşzamanlı olarak birleştirilebilir ve etkin olabilir. Örneğin, bir uygulama, önizleme kullanım alanı kullanarak kullanıcının kameranın gördüğü resmi görüntülemesine izin verebilir, fotoğraftaki kişilerin gülümsemelerini belirleyen bir görüntü analizi kullanım alanına sahip olabilir ve fotoğraf çekildikten sonra resim çekmek için bir kullanım alanı ekleyebilir.

API modeli

Kitaplıkta çalışmak için şunları belirtirsiniz:

  • Yapılandırma seçenekleriyle istenen kullanım alanı.
  • Dinleyici ekleyerek çıkış verileriyle ne yapmalı?
  • Kullanım alanını Android Mimarisi Yaşam Döngüleri'ne 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 (KameraX'ı kullanmanın en basit yolunu istiyorsanız idealdir) veya CameraProvider (daha fazla esnekliğe ihtiyacınız varsa harikadır).

Kamera Kumandası

CameraController, CameraX temel işlevlerinin çoğunu tek bir sınıfta sağlar. Az kurulum kodu gerektirir ve kamerayı başlatma, kullanım alanı yönetimi, hedef döndürme, dokunarak odaklamak için dokunma, yakınlaştırmak için sıkıştırma ve diğer işlemleri otomatik olarak yapar. CameraController öğesini genişleten somut sınıf LifecycleCameraController şeklindedir.

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 değerleri Preview, ImageCapture ve ImageAnalysis şeklindedir. ImageCapture veya ImageAnalysis özelliğini devre dışı bırakmak ya da VideoCapture özelliğini etkinleştirmek için setEnabledUseCases() yöntemini kullanın.

CameraController ürününün diğer kullanım şekilleri için QR Kodu tarayıcı örneğine veya CameraController ile ilgili temel bilgiler videosunu izleyin.

Kamera Sağlayıcısı

CameraProvider kullanımı yine de kolaydır ancak kurulumun daha büyük bir kısmını uygulama geliştiricisi yaptığı için yapılandırmayı özelleştirmek için daha fazla fırsat sunulabilir. Örneğin, çıkış resmi rotasyonunu etkinleştirebilir veya ImageAnalysis ürününde çıkış resmi biçimini ayarlayabilirsiniz. Ayrıca, kamera önizlemesi için özel bir Surface kullanabilirsiniz. Böylece, daha fazla esneklik elde ederken CameraController'da PreviewView kullanmanız gerekir. Uygulamanızın diğer bölümlerine giriş niteliğindeyse mevcut Surface kodunuzu kullanmak yararlı olabilir.

Kullanım alanlarını set() yöntemleriyle yapılandırır ve build() yöntemiyle sonuçlandırırsınız. Her kullanım alanı nesnesi, kullanım alanına özel bir dizi API sağlar. Örneğin, görüntü yakalama kullanım alanı bir takePicture() yöntem çağrısı sağlar.

Uygulama, onResume() ve onPause() içinde belirli bir başlatma ve durdurma yöntemi çağrıları yapmak yerine, cameraProvider.bindToLifecycle() kullanarak kameranın ilişkilendirileceği bir yaşam döngüsü belirler. Bu yaşam döngüsü daha sonra CameraX'e, kamera çekim oturumunun ne zaman yapılandırılacağı konusunda bilgi verir ve kamera durumu değişikliklerinin yaşam döngüsü geçişlerine uygun şekilde yapılmasını sağlar.

Her bir kullanım alanıyla ilgili uygulama adımları için Önizleme uygulama, Resimleri analiz etme, Görüntü yakalama ve Video yakalama konularına bakın.

Önizleme kullanım alanı, görüntülü reklam için Surface ile etkileşimde bulunur. Uygulamalar, kullanım alanını aşağıdaki kodu kullanarak yapılandırma seçenekleriyle 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ı, çekim oturumunun ne zaman oluşturulacağını ve ne zaman durup kapatılacağını belirlemek için bir yaşam döngüsü gözlemler. Kullanım alanı API'leri, ilerlemeyi izlemek için yöntem çağrıları ve geri çağırmalar 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ırın ve ardından parçalar arasında geçiş yapın.
  • Özel bir yaşam döngüsü bileşeni oluşturup bu bileşenle kamera yaşam döngüsünü manuel olarak kontrol etme

Görünüm ve kamera kullanım alanlarınızın yaşam döngüsü sahiplerini ayırırsanız (örneğin, özel bir yaşam döngüsü veya saklama parçası kullanıyorsanız) ProcessCameraProvider.unbindAll() kullanarak veya her bir kullanım alanının bağlantısını ayrı ayrı kaldırarak tüm kullanım alanlarının CameraX'ten bağlantısının kaldırıldığından emin olmanız gerekir. Alternatif olarak, kullanım alanlarını bir Yaşam Döngüsü'ne bağladığınızda KameraX'in yakalama oturumunun açılıp kapatılmasını ve kullanım alanlarının bağlantısını kesmesini sağlayabilirsiniz.

Kameranızın tüm işlevleri, yaşam döngüsüne duyarlı tek bir bileşenin (ör. AppCompatActivity veya AppCompat parçası) yaşam döngüsüne karşılık geliyorsa istenen tüm kullanım alanlarını bağlarken o bileşenin yaşam döngüsünü kullanmak, yaşam döngüsüne duyarlı bileşen etkin olduğunda kamera işlevselliğinin hazır olmasını ve herhangi bir kaynağı tüketmeden güvenli bir şekilde imha edilmesini sağlar.

Özel Yaşam Döngüsü Sahipleri

İleri düzey durumlarda, uygulamanızı 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;
    }
}

Uygulamanız bu LifecycleOwner öğesini kullanarak kodunda istenen noktalara durum geçişleri yerleştirebilir. Bu işlevi uygulamanızda kullanma hakkında daha fazla bilgi için Özel Yaşam Döngüsü Sahiplerini Uygulama konusuna bakın.

Eş zamanlı kullanım alanları

Kullanım alanları eş zamanlı olarak çalışabilir. Kullanım alanları sıralı olarak bir yaşam döngüsüne bağlı olsa da tüm kullanım alanlarını tek bir 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 işleme bölümüne bakın.

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

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

Aşağıdaki yapılandırma kombinasyonlarının destekleneceği garanti edilir (Önizleme veya Video Yakalama gerekli olduğunda ancak aynı anda ikisi birden gerekli değildir):

Önizleme veya Video Yakalama Görüntü yakalama Analiz Açıklamalar
Kullanıcıya bir önizleme veya video kaydedin, fotoğraf çekin ve görüntü akışını analiz edin.
  Bir fotoğraf çekin ve görüntü akışını analiz edin.
  Kullanıcıya bir önizleme veya video kaydı sağlayın ve fotoğraf çekin.
  Kullanıcıya bir önizleme veya video kaydı sunun ve görüntü akışını analiz edin.

Hem Önizleme hem de Video Yakalama gerekli olduğunda aşağıdaki kullanım alanı kombinasyonları koşullu olarak desteklenir:

Önizle Video çekimi Görüntü yakalama Analiz Özel koşul
    Tüm kameralar için garantili
  LIMITED (veya daha iyi) kameralı cihaz.
  LEVEL_3 (veya daha iyi) kamera cihazı.

Ayrıca,

  • Her kullanım alanı kendi başına işe yarayabilir. Örneğin, bir uygulama önizleme 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 eklemek de mümkün olmayabilir. VideoCapture kullanım alanı için uzantılar etkinleştirilemez. Ayrıntılar için Uzantı referansı belgesi'ni inceleyin.
  • Kamera kapasitesine bağlı olarak, bazı kameralar düşük çözünürlük modlarında bu kombinasyonu destekleyebilir, ancak bazı yüksek çözünürlüklerde aynı kombinasyonu destekleyemez.

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

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

İzinler

Uygulamanızın CAMERA iznine ihtiyacı olacak. Resimleri dosyalara kaydetmek için WRITE_EXTERNAL_STORAGE izni de gereklidir (Android 10 veya sonraki sürümleri çalıştıran cihazlar hariç).

Uygulamanızın izinlerini yapılandırma hakkında daha fazla bilgi için Uygulama İzni İsteme bölümünü okuyun.

Gereksinimler

CameraX aşağıdaki minimum sürüm gereksinimlerine sahiptir:

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

Yaşam döngüsüne duyarlı etkinlikler için FragmentActivity veya AppCompatActivity kullanın.

Bağımlılıkları belirtme

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

Projeniz için settings.gradle dosyasını açın ve google() deposunu aşağıda gösterildiği gibi ekleyin:

Eski

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

Kotlin

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

Aşağıdakini Android bloğunun sonuna ekleyin:

Eski

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

Uygulama için her modülün build.gradle dosyasına aşağıdakileri ekleyin:

Modern

dependencies {
  // CameraX core library using the camera2 implementation
  def camerax_version = "1.4.0-beta02"
  // 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.4.0-beta02"
    // 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 uyacak şekilde yapılandırma hakkında daha fazla bilgi edinmek için Bağımlılıkları bildirme bölümüne bakın.

Camera2 ile CameraX birlikte çalışabilirliği

CameraX, Kamera2'de yerleşik olarak bulunur ve CameraX, Camera2 uygulamasında özellikleri okuma ve hatta yazma yöntemlerini gösterir. Tüm ayrıntılar için Interop paketine göz atın.

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

Aşağıdaki kod örneğinde, görüntülü görüşme için optimizasyon yapmak amacıyla akış kullanım alanları kullanılmaktadır. Görüntülü görüşme akışı kullanım alanının mevcut olup olmadığını öğrenmek için Camera2CameraInfo simgesini kullanın. Ardından, temel akış kullanım alanını belirlemek için bir Camera2Interop.Extender 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 bakın.

Kod Laboratuvarı

  • CameraX'i Kullanmaya Başlama
  • Kod örneği

  • CameraX örnek uygulamaları