2026'da Android CameraX: Mülakat Sorularıyla Fotoğraf ve Video Çekimi

Preview, ImageCapture ve VideoCapture kullanım durumlarını kapsayan Android CameraX 1.6 eğitimi. Kotlin kodu, Compose entegrasyonu ve mülakat soruları içerir.

2026'da Android CameraX: Mülakat Sorularıyla Fotoğraf ve Video Çekimi

Android CameraX, donanım karmaşıklığını yaşam döngüsü farkında bir API arkasında soyutlayarak kamera geliştirmeyi basitleştirir. Artık kararlı olan 1.6.2 sürümü ve CameraPipe'a geçişin tamamlanmasıyla birlikte CameraX, Pixel kamera uygulamasını destekleyen aynı yüksek performanslı kamera yığınını sunar.

CameraX 1.6 Temel Değişiklikler

CameraX 1.6, CameraPipe'a geçiş yaptı, VideoCapture için varsayılan olarak Media3 Muxer kullanıyor ve SessionConfig API'sini stabilize etti. Kotlin DSL oluşturucuları (preview { }, imageCapture { }, videoCapture { }) standart kodu %40 azaltır.

CameraX Mimarisi ve Kullanım Durumu Modeli

CameraX eşzamanlı çalışabilen dört birincil kullanım durumu sağlar: Preview, ImageCapture, ImageAnalysis ve VideoCapture. Her kullanım durumu bir LifecycleOwner'a bağlanır, böylece kamera activity veya fragment ile otomatik olarak başlar ve durur.

CameraProvider, bu kullanım durumlarını örnekleyen ve kameraya bağlayan bir fabrika görevi görür. Bu ayrıştırma, aynı kodun satıcıya özgü tuhaflıklar hakkında endişelenmeden farklı OEM'lerin cihazlarında çalışması anlamına gelir.

CameraSetup.ktkotlin
class CameraSetup(
    private val context: Context,
    private val lifecycleOwner: LifecycleOwner
) {
    private lateinit var cameraProvider: ProcessCameraProvider
    private var imageCapture: ImageCapture? = null
    private var videoCapture: VideoCapture<Recorder>? = null
    
    suspend fun initialize() {
        // ProcessCameraProvider binds use cases to lifecycle
        cameraProvider = ProcessCameraProvider.getInstance(context).await()
    }
    
    fun bindUseCases(previewView: PreviewView) {
        // Unbind existing use cases before rebinding
        cameraProvider.unbindAll()
        
        // Preview use case displays camera feed
        val preview = Preview.Builder()
            .build()
            .apply { setSurfaceProvider(previewView.surfaceProvider) }
        
        // ImageCapture for photos
        imageCapture = ImageCapture.Builder()
            .setCaptureMode(ImageCapture.CAPTURE_MODE_MINIMIZE_LATENCY)
            .build()
        
        // VideoCapture with Recorder
        val recorder = Recorder.Builder()
            .setQualitySelector(QualitySelector.from(Quality.FHD))
            .build()
        videoCapture = VideoCapture.withOutput(recorder)
        
        // Bind all use cases to lifecycle
        cameraProvider.bindToLifecycle(
            lifecycleOwner,
            CameraSelector.DEFAULT_BACK_CAMERA,
            preview,
            imageCapture,
            videoCapture
        )
    }
}

bindToLifecycle çağrısı, kullanım durumlarını hem kamera donanımına hem de yaşam döngüsüne bağlar. LifecycleOwner STARTED durumuna girdiğinde kamera açılır. STOPPED durumuna girdiğinde kamera otomatik olarak kapanır.

ImageCapture ile Fotoğraf Çekimi Uygulaması

ImageCapture iki yakalama modu sağlar: hızlı deklanşör yanıtı için CAPTURE_MODE_MINIMIZE_LATENCY ve işlem yoğun çekimler için CAPTURE_MODE_MAXIMIZE_QUALITY. Seçim, uygulamanın hızı mı (sosyal uygulamalar) yoksa kaliteyi mi (belge tarayıcılar) önceliklendirdiğine bağlıdır.

PhotoCaptureManager.ktkotlin
class PhotoCaptureManager(
    private val context: Context,
    private val imageCapture: ImageCapture
) {
    private val mainExecutor = ContextCompat.getMainExecutor(context)
    
    fun capturePhoto(onResult: (Uri?) -> Unit) {
        // Generate unique filename with timestamp
        val filename = "IMG_${System.currentTimeMillis()}.jpg"
        
        val contentValues = ContentValues().apply {
            put(MediaStore.MediaColumns.DISPLAY_NAME, filename)
            put(MediaStore.MediaColumns.MIME_TYPE, "image/jpeg")
            // Store in Pictures/CameraX folder on Android 10+
            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
                put(MediaStore.Images.Media.RELATIVE_PATH, "Pictures/CameraX")
            }
        }
        
        val outputOptions = ImageCapture.OutputFileOptions.Builder(
            context.contentResolver,
            MediaStore.Images.Media.EXTERNAL_CONTENT_URI,
            contentValues
        ).build()
        
        imageCapture.takePicture(
            outputOptions,
            mainExecutor,
            object : ImageCapture.OnImageSavedCallback {
                override fun onImageSaved(results: ImageCapture.OutputFileResults) {
                    // results.savedUri contains the MediaStore URI
                    onResult(results.savedUri)
                }
                
                override fun onError(exception: ImageCaptureException) {
                    Log.e("PhotoCapture", "Capture failed: ${exception.message}")
                    onResult(null)
                }
            }
        )
    }
}

CameraX 1.5, işlenmemiş sensör verilerine ihtiyaç duyan uygulamalar için DNG (RAW) yakalama desteği ekledi. RAW çıktısını etkinleştirmeden önce ImageCapture.getImageCaptureCapabilities() ile cihaz yeteneği kontrol edilmelidir.

VideoCapture ve Recorder ile Video Kaydı

VideoCapture, kodlama ve karıştırmayı işlemek için bir Recorder nesnesi kullanır. Recorder API, ses senkronizasyonunu otomatik olarak işleyen bir hazırla-başlat-durdur düzeni izler.

VideoRecordingManager.ktkotlin
class VideoRecordingManager(
    private val context: Context,
    private val videoCapture: VideoCapture<Recorder>
) {
    private var activeRecording: Recording? = null
    
    fun startRecording(onEvent: (VideoRecordEvent) -> Unit): Boolean {
        // Check if already recording
        if (activeRecording != null) return false
        
        val filename = "VID_${System.currentTimeMillis()}.mp4"
        
        val contentValues = ContentValues().apply {
            put(MediaStore.MediaColumns.DISPLAY_NAME, filename)
            put(MediaStore.MediaColumns.MIME_TYPE, "video/mp4")
            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
                put(MediaStore.Video.Media.RELATIVE_PATH, "Movies/CameraX")
            }
        }
        
        val mediaStoreOutput = MediaStoreOutputOptions.Builder(
            context.contentResolver,
            MediaStore.Video.Media.EXTERNAL_CONTENT_URI
        )
            .setContentValues(contentValues)
            .build()
        
        // Prepare recording with audio if permission granted
        val pendingRecording = videoCapture.output
            .prepareRecording(context, mediaStoreOutput)
        
        if (hasAudioPermission()) {
            pendingRecording.withAudioEnabled()
        }
        
        // Start recording and store reference
        activeRecording = pendingRecording.start(
            ContextCompat.getMainExecutor(context)
        ) { event ->
            onEvent(event)
            
            // Clear reference when recording completes
            if (event is VideoRecordEvent.Finalize) {
                activeRecording = null
            }
        }
        
        return true
    }
    
    fun stopRecording() {
        activeRecording?.stop()
    }
    
    fun pauseRecording() {
        activeRecording?.pause()
    }
    
    fun resumeRecording() {
        activeRecording?.resume()
    }
    
    private fun hasAudioPermission(): Boolean {
        return ContextCompat.checkSelfPermission(
            context,
            Manifest.permission.RECORD_AUDIO
        ) == PackageManager.PERMISSION_GRANTED
    }
}

CameraX 1.5, ağır çekim video desteği ekledi. 120fps veya 240fps kaydı etkinleştirmeden önce Recorder.getHighSpeedVideoCapabilities() ile yetenekleri sorgulayın.

Android mülakatlarında başarılı olmaya hazır mısın?

İnteraktif simülatörler, flashcards ve teknik testlerle pratik yap.

Jetpack Compose ile CameraX

CameraX 1.5, CameraXViewfinder composable'ı ile camera-compose artifact'ını tanıttı. View tabanlı PreviewView kullanan uygulamalar için AndroidView, birlikte çalışabilirlik sağlar.

CameraPreviewComposable.ktkotlin
@Composable
fun CameraPreview(
    modifier: Modifier = Modifier,
    onPreviewViewCreated: (PreviewView) -> Unit
) {
    AndroidView(
        modifier = modifier.fillMaxSize(),
        factory = { context ->
            PreviewView(context).apply {
                implementationMode = PreviewView.ImplementationMode.COMPATIBLE
                scaleType = PreviewView.ScaleType.FILL_CENTER
                onPreviewViewCreated(this)
            }
        }
    )
}

@Composable
fun CameraScreen(viewModel: CameraViewModel = viewModel()) {
    val context = LocalContext.current
    val lifecycleOwner = LocalLifecycleOwner.current
    
    LaunchedEffect(Unit) {
        viewModel.initializeCamera(context, lifecycleOwner)
    }
    
    Box(modifier = Modifier.fillMaxSize()) {
        CameraPreview(
            onPreviewViewCreated = { previewView ->
                viewModel.bindPreview(previewView)
            }
        )
        
        // Capture buttons overlay
        Row(
            modifier = Modifier
                .align(Alignment.BottomCenter)
                .padding(32.dp),
            horizontalArrangement = Arrangement.spacedBy(24.dp)
        ) {
            IconButton(
                onClick = { viewModel.capturePhoto() }
            ) {
                Icon(Icons.Default.Camera, "Take photo")
            }
            
            IconButton(
                onClick = { viewModel.toggleRecording() }
            ) {
                Icon(
                    if (viewModel.isRecording) Icons.Default.Stop
                    else Icons.Default.Videocam,
                    "Record video"
                )
            }
        }
    }
}

Compose öncelikli uygulamalar için Jetpack Compose mülakat soruları kılavuzu, doğrudan kamera durum yönetimine uygulanan ViewModel entegrasyon kalıplarını kapsar.

Kamera İzinlerinin Yönetimi

Android, çalışma zamanında CAMERA izni gerektirir. RECORD_AUDIO yalnızca sesli video kaydederken gereklidir. İzin akışı, istemeden önce erişimin neden gerekli olduğunu açıklamalıdır.

PermissionHandler.ktkotlin
class CameraPermissionHandler(private val activity: ComponentActivity) {
    private val requiredPermissions = arrayOf(
        Manifest.permission.CAMERA,
        Manifest.permission.RECORD_AUDIO
    )
    
    private val permissionLauncher = activity.registerForActivityResult(
        ActivityResultContracts.RequestMultiplePermissions()
    ) { permissions ->
        val cameraGranted = permissions[Manifest.permission.CAMERA] == true
        val audioGranted = permissions[Manifest.permission.RECORD_AUDIO] == true
        
        if (cameraGranted) {
            onCameraPermissionGranted(audioGranted)
        } else {
            onCameraPermissionDenied()
        }
    }
    
    fun checkAndRequestPermissions() {
        when {
            hasAllPermissions() -> onCameraPermissionGranted(hasAudioPermission())
            shouldShowRationale() -> showPermissionRationale()
            else -> permissionLauncher.launch(requiredPermissions)
        }
    }
    
    private fun hasAllPermissions(): Boolean {
        return requiredPermissions.all { permission ->
            ContextCompat.checkSelfPermission(
                activity, permission
            ) == PackageManager.PERMISSION_GRANTED
        }
    }
    
    private fun hasAudioPermission(): Boolean {
        return ContextCompat.checkSelfPermission(
            activity,
            Manifest.permission.RECORD_AUDIO
        ) == PackageManager.PERMISSION_GRANTED
    }
    
    private fun shouldShowRationale(): Boolean {
        return requiredPermissions.any { permission ->
            ActivityCompat.shouldShowRequestPermissionRationale(activity, permission)
        }
    }
}

CameraX Mülakat Soruları

CameraX, kamera entegrasyonu, yaşam döngüsü yönetimi veya donanım soyutlaması tartışılırken Android mülakatlarında karşımıza çıkar. Bu sorular mimari anlayışını ve pratik uygulama detaylarını test eder.

Camera2 yerine neden CameraX kullanılmalı?

CameraX, Camera2'nin doğrudan açığa çıkardığı cihaza özgü tuhaflıkları soyutlar. Bir Camera2 uygulaması, yüzlerce cihaza özgü geçici çözümün işlenmesini gerektirir. CameraX bu düzeltmeleri kitaplığa yerleştirir ve 150'den fazla cihaz modelini kapsayan CameraX Test Lab'da test eder.

Yaşam döngüsü farkında bağlama, manuel kaynak yönetimini ortadan kaldırır. Camera2, her yaşam döngüsü geri çağrısında doğru şekilde işlenmediğinde sızıntılara neden olan açık open/close çağrıları gerektirir.

CameraProvider kullanım durumlarını yaşam döngüsüne nasıl bağlar?

CameraProvider dahili olarak LifecycleObserver desenini kullanır. bindToLifecycle() çağrılırken, sağlanan LifecycleOwner'a bir gözlemci kaydeder. Bu gözlemci, kamerayı açmak ve kapatmak için ON_START ve ON_STOP olaylarını alır.

Önemli nokta: CameraX, bağlamada kamerayı hemen başlatmaz. Yaşam döngüsünün STARTED durumuna ulaşmasını bekler, bu da Activity.onStart() zamanlamasıyla eşleşir.

Uyumsuz kullanım durumları bağlandığında ne olur?

Tüm kullanım durumu kombinasyonları tüm cihazlarda çalışmaz. Preview + VideoCapture + ImageAnalysis + ImageCapture eski donanımlarda başarısız olabilir. CameraX, çalışma zamanında değil bağlama zamanında IllegalArgumentException fırlatır.

Çözüm, karmaşık kombinasyonları bağlamadan önce CameraProvider.hasCamera() ve cihaz yeteneklerini kontrol etmektir. Kritik uygulamalar için düşük kaliteli cihazlarda açıkça test edin.

CAPTURE_MODE_MINIMIZE_LATENCY ve CAPTURE_MODE_MAXIMIZE_QUALITY arasındaki farkı açıklayın

MINIMIZE_LATENCY, daha hızlı işleme hatları kullanarak deklanşör gecikmesini azaltır ve muhtemelen bazı son işlemeleri atlar. MAXIMIZE_QUALITY, desteklenen cihazlarda tam HDR+ işleme, gürültü azaltma ve çoklu kare yakalama uygular.

Takas: gecikme modu 100-200ms'de yakalar, kalite modu aydınlatmaya bağlı olarak 500ms-1s sürebilir. Sosyal uygulamalar genellikle gecikmeyi seçer. Belge tarama uygulamaları kaliteyi seçer.

CameraX cihaz rotasyonunu nasıl yönetir?

CameraX, hedef rotasyon ayarı aracılığıyla rotasyonu otomatik olarak yönetir. Varsayılan olarak Ekran rotasyonunu kullanır, ancak uygulamalar setTargetRotation() ile geçersiz kılabilir. Çıktı görüntüsü EXIF verileri doğru yönlendirme etiketini içerir.

PreviewView için scaleType, en boy oranı farklılıklarını yönetir. FILL_CENTER doldurmak için kırpar, FIT_CENTER letterboxing gösterir. Seçim, uygulamanın tam ekran önizlemeyi mi yoksa kırpmayı önlemeyi mi önceliklendirdiğine bağlıdır.

CameraX 1.6 için Bağımlılıklar ve Kurulum

CameraX kitaplığı birden fazla artifact'a bölünmüştür. APK boyutunu en aza indirmek için yalnızca uygulamanın kullandığını ekleyin.

build.gradle.kts (Module: app)kotlin
dependencies {
    val cameraxVersion = "1.6.2"
    
    // Core library required for all use cases
    implementation("androidx.camera:camera-core:$cameraxVersion")
    
    // Camera2 implementation (required)
    implementation("androidx.camera:camera-camera2:$cameraxVersion")
    
    // Lifecycle integration
    implementation("androidx.camera:camera-lifecycle:$cameraxVersion")
    
    // VideoCapture use case
    implementation("androidx.camera:camera-video:$cameraxVersion")
    
    // PreviewView and camera UI components
    implementation("androidx.camera:camera-view:$cameraxVersion")
    
    // Optional: Extensions (Night mode, HDR, etc.)
    implementation("androidx.camera:camera-extensions:$cameraxVersion")
    
    // Optional: Real-time effects
    implementation("androidx.camera:camera-effects:$cameraxVersion")
}

android {
    // CameraX requires Java 11 bytecode
    compileOptions {
        sourceCompatibility = JavaVersion.VERSION_11
        targetCompatibility = JavaVersion.VERSION_11
    }
}

Manifest, özellik bildirimleri ve izinler gerektirir:

xml
<!-- AndroidManifest.xml -->
<manifest>
    <!-- Camera hardware requirement -->
    <uses-feature android:name="android.hardware.camera.any" />
    
    <!-- Runtime permissions -->
    <uses-permission android:name="android.permission.CAMERA" />
    <uses-permission android:name="android.permission.RECORD_AUDIO" />
</manifest>

Kotlin Coroutines için ilgili kalıplar, CameraX ListenableFuture çağrılarını suspend fonksiyonlarına sararken uygulanır.

Pratik yapmaya başla!

Mülakat simülatörleri ve teknik testlerle bilgini test et.

CameraX 1.6 Üretim Uygulamaları için Neleri Değiştiriyor

CameraX 1.6, mevcut uygulamaları etkileyen üç değişiklik getirdi:

  1. CameraPipe arka ucu: Dahili kamera yığını artık Pixel kamerayla aynı mimari olan CameraPipe'ı kullanıyor. Bu, Pixel cihazlarda performansı artırır ve gelişmiş özellikler için daha temiz bir temel sağlar. Mevcut kod değişiklik gerektirmez.

  2. Varsayılan Media3 Muxer: VideoCapture artık MediaMuxer yerine Media3 Muxer kullanıyor. Bu, çökme dayanıklılığını artırır: uygulama kayıt sırasında sonlandırılırsa video dosyası oynatılabilir kalır. API yüzeyi değişmedi.

  3. Kararlı SessionConfig API: Uygulamalar artık deneysel açıklamalar olmadan SessionConfig aracılığıyla gelişmiş kamera ayarlarını yapılandırabilir. Bu, desteklenen cihazlarda eşzamanlı ön/arka kamera kullanımı gibi özellikleri etkinleştirir.

Geçiş yolu: Bağımlılık sürümünü güncelleyin. Daha önce sorun yaşayan cihazlarda test edin. CameraX sürüm notları sürümler arasındaki davranış değişikliklerini belgeler.

  • CameraX yaşam döngüsü farkında bağlama kullanır: bindToLifecycle() kullanım durumlarını hem kameraya hem de Activity yaşam döngüsüne bağlar
  • ImageCapture modları gecikme ile kalite arasında takas yapar: cihaz yeteneğine değil kullanım durumuna göre seçin
  • VideoCapture, bağlamadan önce Recorder kurulumu gerektirir: başlamadan önce çıktı seçeneklerini hazırlayın
  • İzin işleme, istemeden önce amacı açıklamalıdır: ret oranlarını azaltır
  • CameraX 1.6 dahili olarak CameraPipe'a geçiş yaptı: API değişikliği gerekmiyor, ancak hedef cihazlarda test edin
  • Mülakat soruları yaşam döngüsü yönetimi, kullanım durumu kombinasyonları ve Camera2 karşılaştırmasına odaklanır
Günün meydan okuması

Android kodundaki hatayı bulabilir misin?

Gerçek bir kod parçası, gizli bir hata, günde bir deneme. Denemek için hesap gerekmez.

Anthony Fillion-Maillet

Yazan:

Anthony Fillion-Maillet

SharpSkill kurucusu

10 yılı aşkın süredir fullstack geliştirici. SharpSkill’i yönetiyor ve burada yayımlanan her şeyden sorumlu.

11 Eylül 2026 tarihinde güncellendi

Paylaş

İlgili makaleler