# Android CameraX у 2026: Захоплення Фото та Відео з Питаннями для Співбесід > Посібник з Android CameraX 1.6, що охоплює випадки використання Preview, ImageCapture та VideoCapture. Містить код Kotlin, інтеграцію з Compose та питання для співбесід. - Published: 2026-09-11 - Updated: 2026-09-11 - Author: Anthony Fillion-Maillet - Reading time: 5 min --- Android CameraX спрощує розробку камери шляхом абстрагування апаратної складності за допомогою API, що враховує життєвий цикл. З версією 1.6.2, яка тепер стабільна, та завершеною міграцією на CameraPipe, CameraX надає той самий високопродуктивний стек камери, що живить додаток камери Pixel. > **Ключові Зміни в CameraX 1.6** > > CameraX 1.6 мігрував на CameraPipe, за замовчуванням використовує Media3 Muxer для VideoCapture та стабілізував API SessionConfig. Kotlin DSL builders (`preview { }`, `imageCapture { }`, `videoCapture { }`) зменшують шаблонний код на 40%. ## Архітектура CameraX та Модель Випадків Використання CameraX надає чотири основні випадки використання, які можуть працювати одночасно: Preview, ImageCapture, ImageAnalysis та VideoCapture. Кожен випадок використання прив'язується до [LifecycleOwner](https://developer.android.com/topic/libraries/architecture/lifecycle), тому камера автоматично запускається та зупиняється разом з activity або fragment. CameraProvider діє як фабрика, що створює екземпляри цих випадків використання та прив'язує їх до камери. Це розділення означає, що той самий код працює на пристроях різних виробників без турботи про специфічні особливості постачальників. ```kotlin // CameraSetup.kt class CameraSetup( private val context: Context, private val lifecycleOwner: LifecycleOwner ) { private lateinit var cameraProvider: ProcessCameraProvider private var imageCapture: ImageCapture? = null private var videoCapture: VideoCapture? = 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` з'єднує випадки використання як з апаратним забезпеченням камери, так і з життєвим циклом. Коли LifecycleOwner входить у стан STARTED, камера відкривається. Коли входить у стан STOPPED, камера автоматично закривається. ## Реалізація Захоплення Фото з ImageCapture ImageCapture пропонує два режими захоплення: `CAPTURE_MODE_MINIMIZE_LATENCY` для швидкої реакції затвора та `CAPTURE_MODE_MAXIMIZE_QUALITY` для знімків з інтенсивною обробкою. Вибір залежить від того, чи додаток пріоритезує швидкість (соціальні додатки) чи якість (сканери документів). ```kotlin // PhotoCaptureManager.kt 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 додав підтримку захоплення DNG (RAW) для додатків, що потребують необроблених даних сенсора. Перевірте можливості пристрою за допомогою `ImageCapture.getImageCaptureCapabilities()` перед увімкненням виводу RAW. ## Запис Відео з VideoCapture та Recorder VideoCapture використовує об'єкт [Recorder](https://developer.android.com/reference/androidx/camera/video/Recorder) для обробки кодування та мікшування. API Recorder дотримується шаблону підготувати-почати-зупинити, який автоматично обробляє синхронізацію аудіо. ```kotlin // VideoRecordingManager.kt class VideoRecordingManager( private val context: Context, private val videoCapture: VideoCapture ) { 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 додав підтримку уповільненого відео. Запитуйте можливості за допомогою `Recorder.getHighSpeedVideoCapabilities()` перед увімкненням запису 120fps або 240fps. ## CameraX з Jetpack Compose CameraX 1.5 представив артефакт `camera-compose` з composable `CameraXViewfinder`. Для додатків, що досі використовують PreviewView на основі View, AndroidView забезпечує сумісність. ```kotlin // CameraPreviewComposable.kt @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, посібник [питань для співбесід Jetpack Compose](/technologies/android/interview-questions/android-compose) охоплює шаблони інтеграції ViewModel, що безпосередньо застосовуються до керування станом камери. ## Обробка Дозволів Камери Android вимагає дозволу CAMERA під час виконання. RECORD_AUDIO потрібен лише при записі відео зі звуком. Потік дозволів повинен пояснювати, чому потрібен доступ, перед запитом. ```kotlin // PermissionHandler.kt 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 CameraX з'являється на співбесідах Android при обговоренні інтеграції камери, керування життєвим циклом або апаратної абстракції. Ці питання тестують розуміння архітектури та практичних деталей реалізації. ### Чому використовувати CameraX замість Camera2? CameraX абстрагує специфічні для пристроїв особливості, які Camera2 експонує безпосередньо. Реалізація Camera2 вимагає обробки сотень специфічних для пристроїв обхідних рішень. CameraX вбудовує ці виправлення в бібліотеку, тестовану на [CameraX Test Lab](https://android-developers.googleblog.com/2025/11/introducing-camerax-15-powerful-video.html), що охоплює понад 150 моделей пристроїв. Прив'язка, що враховує життєвий цикл, усуває ручне керування ресурсами. Camera2 вимагає явних викликів open/close, які спричиняють витоки, якщо не обробляються правильно в кожному зворотному виклику життєвого циклу. ### Як CameraProvider прив'язує випадки використання до життєвого циклу? CameraProvider внутрішньо використовує шаблон LifecycleObserver. При виклику `bindToLifecycle()` реєструє спостерігача на наданому LifecycleOwner. Цей спостерігач отримує події ON_START та ON_STOP для відкриття та закриття камери. Ключовий момент: CameraX не запускає камеру негайно при прив'язці. Він чекає, поки життєвий цикл досягне стану STARTED, що відповідає часу Activity.onStart(). ### Що відбувається, коли прив'язуються несумісні випадки використання? Не всі комбінації випадків використання працюють на всіх пристроях. Preview + VideoCapture + ImageAnalysis + ImageCapture може не працювати на старішому обладнанні. CameraX викидає IllegalArgumentException під час прив'язки, а не під час виконання. Рішення — перевірка `CameraProvider.hasCamera()` та можливостей пристрою перед прив'язкою складних комбінацій. Для критичних додатків явно тестуйте на пристроях низького класу. ### Поясніть різницю між CAPTURE_MODE_MINIMIZE_LATENCY та CAPTURE_MODE_MAXIMIZE_QUALITY MINIMIZE_LATENCY зменшує затримку затвора шляхом використання швидших конвеєрів обробки, можливо пропускаючи деяку пост-обробку. MAXIMIZE_QUALITY застосовує повну обробку HDR+, зменшення шуму та багатокадрове захоплення на підтримуваних пристроях. Компроміс: режим затримки захоплює за 100-200мс, режим якості може займати 500мс-1с залежно від освітлення. Соціальні додатки зазвичай обирають затримку. Додатки для сканування документів обирають якість. ### Як CameraX обробляє обертання пристрою? CameraX автоматично обробляє обертання через налаштування цільового обертання. За замовчуванням використовує обертання дисплея, але додатки можуть перевизначити за допомогою `setTargetRotation()`. Дані EXIF вихідного зображення містять правильний тег орієнтації. Для PreviewView, scaleType обробляє відмінності співвідношення сторін. FILL_CENTER обрізає для заповнення, FIT_CENTER показує letterboxing. Вибір залежить від того, чи додаток пріоритезує повноекранний попередній перегляд чи уникнення обрізки. ## Залежності та Налаштування для CameraX 1.6 Бібліотека CameraX розділена на кілька артефактів. Додавайте лише те, що використовує додаток, щоб мінімізувати розмір APK. ```kotlin // build.gradle.kts (Module: app) 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 } } ``` Маніфест потребує оголошень функцій та дозволів: ```xml ``` Пов'язані шаблони для [Kotlin Coroutines](/blog/android/mastering-kotlin-coroutines) застосовуються при обгортанні викликів CameraX ListenableFuture у suspend функції. ## Що CameraX 1.6 Змінює для Продакшн Додатків CameraX 1.6 приніс три зміни, що впливають на існуючі реалізації: 1. **Бекенд CameraPipe**: Внутрішній стек камери тепер використовує CameraPipe, ту саму архітектуру, що й камера Pixel. Це покращує продуктивність на пристроях Pixel та забезпечує чистішу основу для розширених функцій. Існуючий код не потребує змін. 2. **Media3 Muxer за замовчуванням**: VideoCapture тепер використовує Media3 Muxer замість MediaMuxer. Це покращує стійкість до збоїв: якщо додаток завершується під час запису, відеофайл залишається відтворюваним. Поверхня API не змінилася. 3. **Стабільний API SessionConfig**: Додатки тепер можуть налаштовувати розширені параметри камери через SessionConfig без експериментальних анотацій. Це дозволяє такі функції, як одночасне використання передньої та задньої камери на підтримуваних пристроях. **Шлях міграції**: Оновіть версію залежності. Протестуйте на пристроях, що раніше мали проблеми. [Примітки до випуску CameraX](https://developer.android.com/jetpack/androidx/releases/camera) документують будь-які зміни поведінки між версіями. - CameraX використовує прив'язку, що враховує життєвий цикл: `bindToLifecycle()` з'єднує випадки використання як з камерою, так і з життєвим циклом Activity - Режими ImageCapture обмінюють затримку на якість: обирайте на основі випадку використання, а не можливостей пристрою - VideoCapture вимагає налаштування Recorder перед прив'язкою: підготуйте параметри виводу перед початком - Обробка дозволів повинна пояснювати мету перед запитом: зменшує рівень відмов - CameraX 1.6 внутрішньо мігрував на CameraPipe: зміни API не потрібні, але тестуйте на цільових пристроях - Питання для співбесід зосереджуються на керуванні життєвим циклом, комбінаціях випадків використання та порівнянні з Camera2 --- Source: SharpSkill (https://sharpskill.dev), tech interview preparation for your real stack. HTML version of this page: https://sharpskill.dev/uk/blog/android/camerax-photo-video-capture-interview-questions