Android CameraX 2026: Foto- und Videoaufnahme mit Interview-Fragen
CameraX Tutorial für Android-Entwickler: Lifecycle-Management, Foto- und Videoaufnahme mit Jetpack Compose und Interview-Fragen.

Android CameraX vereinfacht die Kameraentwicklung, indem es die Hardwarekomplexität hinter einer lebenszyklusabhängigen API abstrahiert. Mit der stabilen Version 1.6.2 und der abgeschlossenen Migration zu CameraPipe liefert CameraX denselben leistungsstarken Kamera-Stack, der auch die Pixel-Kamera-App antreibt.
CameraX 1.6 migrierte zu CameraPipe, verwendet standardmäßig Media3 Muxer für VideoCapture und stabilisierte die SessionConfig-API. Die Kotlin-DSL-Builder (preview { }, imageCapture { }, videoCapture { }) reduzieren Boilerplate-Code um 40%.
CameraX-Architektur und Use-Case-Modell
CameraX stellt vier primäre Use Cases bereit, die gleichzeitig ausgeführt werden können: Preview, ImageCapture, ImageAnalysis und VideoCapture. Jeder Use Case wird an einen LifecycleOwner gebunden, sodass die Kamera automatisch mit der Activity oder dem Fragment startet und stoppt.
Der CameraProvider fungiert als Factory, die diese Use Cases instanziiert und an die Kamera bindet. Diese Entkopplung bedeutet, dass derselbe Code auf Geräten verschiedener OEMs läuft, ohne sich um herstellerspezifische Eigenheiten kümmern zu müssen.
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 bindet Use Cases an den Lebenszyklus
cameraProvider = ProcessCameraProvider.getInstance(context).await()
}
fun bindUseCases(previewView: PreviewView) {
// Bestehende Use Cases vor dem erneuten Binden lösen
cameraProvider.unbindAll()
// Preview Use Case zeigt Kamera-Feed an
val preview = Preview.Builder()
.build()
.apply { setSurfaceProvider(previewView.surfaceProvider) }
// ImageCapture für Fotos
imageCapture = ImageCapture.Builder()
.setCaptureMode(ImageCapture.CAPTURE_MODE_MINIMIZE_LATENCY)
.build()
// VideoCapture mit Recorder
val recorder = Recorder.Builder()
.setQualitySelector(QualitySelector.from(Quality.FHD))
.build()
videoCapture = VideoCapture.withOutput(recorder)
// Alle Use Cases an Lebenszyklus binden
cameraProvider.bindToLifecycle(
lifecycleOwner,
CameraSelector.DEFAULT_BACK_CAMERA,
preview,
imageCapture,
videoCapture
)
}
}Der Aufruf von bindToLifecycle verbindet Use Cases sowohl mit der Kamera-Hardware als auch mit dem Lebenszyklus. Wenn der LifecycleOwner STARTED erreicht, öffnet sich die Kamera. Wenn er STOPPED erreicht, schließt sie sich automatisch.
Implementierung der Fotoaufnahme mit ImageCapture
ImageCapture bietet zwei Aufnahmemodi: CAPTURE_MODE_MINIMIZE_LATENCY für schnelle Auslösereaktion und CAPTURE_MODE_MAXIMIZE_QUALITY für verarbeitungsintensive Aufnahmen. Die Wahl hängt davon ab, ob die App Geschwindigkeit (Social Apps) oder Qualität (Dokumentenscanner) priorisiert.
class PhotoCaptureManager(
private val context: Context,
private val imageCapture: ImageCapture
) {
private val mainExecutor = ContextCompat.getMainExecutor(context)
fun capturePhoto(onResult: (Uri?) -> Unit) {
// Eindeutigen Dateinamen mit Zeitstempel generieren
val filename = "IMG_${System.currentTimeMillis()}.jpg"
val contentValues = ContentValues().apply {
put(MediaStore.MediaColumns.DISPLAY_NAME, filename)
put(MediaStore.MediaColumns.MIME_TYPE, "image/jpeg")
// In Pictures/CameraX-Ordner auf Android 10+ speichern
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 enthält die MediaStore URI
onResult(results.savedUri)
}
override fun onError(exception: ImageCaptureException) {
Log.e("PhotoCapture", "Aufnahme fehlgeschlagen: ${exception.message}")
onResult(null)
}
}
)
}
}CameraX 1.5 fügte DNG (RAW)-Aufnahmeunterstützung für Apps hinzu, die unverarbeitete Sensordaten benötigen. Die Gerätefähigkeit sollte mit ImageCapture.getImageCaptureCapabilities() geprüft werden, bevor RAW-Ausgabe aktiviert wird.
Videoaufnahme mit VideoCapture und Recorder
VideoCapture verwendet ein Recorder-Objekt zur Handhabung von Encoding und Muxing. Die Recorder-API folgt einem Prepare-Start-Stop-Muster, das die Audio-Synchronisation automatisch handhabt.
class VideoRecordingManager(
private val context: Context,
private val videoCapture: VideoCapture<Recorder>
) {
private var activeRecording: Recording? = null
fun startRecording(onEvent: (VideoRecordEvent) -> Unit): Boolean {
// Prüfen ob bereits aufgenommen wird
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()
// Aufnahme mit Audio vorbereiten falls Berechtigung erteilt
val pendingRecording = videoCapture.output
.prepareRecording(context, mediaStoreOutput)
if (hasAudioPermission()) {
pendingRecording.withAudioEnabled()
}
// Aufnahme starten und Referenz speichern
activeRecording = pendingRecording.start(
ContextCompat.getMainExecutor(context)
) { event ->
onEvent(event)
// Referenz löschen wenn Aufnahme abgeschlossen
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 fügte Zeitlupen-Videoaufnahme hinzu. Die Fähigkeiten sollten mit Recorder.getHighSpeedVideoCapabilities() abgefragt werden, bevor 120fps oder 240fps Aufnahme aktiviert wird.
Bereit für deine Android-Interviews?
Übe mit unseren interaktiven Simulatoren, Flashcards und technischen Tests.
CameraX mit Jetpack Compose
CameraX 1.5 führte das camera-compose-Artefakt mit einem CameraXViewfinder-Composable ein. Für Apps, die noch das View-basierte PreviewView verwenden, bietet AndroidView Interoperabilität.
@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)
}
)
// Aufnahme-Buttons Overlay
Row(
modifier = Modifier
.align(Alignment.BottomCenter)
.padding(32.dp),
horizontalArrangement = Arrangement.spacedBy(24.dp)
) {
IconButton(
onClick = { viewModel.capturePhoto() }
) {
Icon(Icons.Default.Camera, "Foto aufnehmen")
}
IconButton(
onClick = { viewModel.toggleRecording() }
) {
Icon(
if (viewModel.isRecording) Icons.Default.Stop
else Icons.Default.Videocam,
"Video aufnehmen"
)
}
}
}
}Für Compose-First-Implementierungen behandelt der Leitfaden zu Jetpack Compose Interview-Fragen ViewModel-Integrationsmuster, die direkt auf die Kamera-Zustandsverwaltung anwendbar sind.
Handhabung von Kamera-Berechtigungen
Android erfordert die CAMERA-Berechtigung zur Laufzeit. RECORD_AUDIO wird nur benötigt, wenn Video mit Ton aufgenommen wird. Der Berechtigungsablauf sollte erklären, warum der Zugriff benötigt wird, bevor er angefordert wird.
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 Interview-Fragen
CameraX erscheint in Android-Interviews bei Diskussionen über Kamera-Integration, Lifecycle-Management oder Hardware-Abstraktion. Diese Fragen testen das Verständnis der Architektur und praktische Implementierungsdetails.
Warum CameraX anstelle von Camera2 verwenden?
CameraX abstrahiert gerätespezifische Eigenheiten, die Camera2 direkt exponiert. Eine Camera2-Implementierung erfordert die Handhabung hunderter gerätespezifischer Workarounds. CameraX baut diese Korrekturen in die Bibliothek ein, getestet gegen das CameraX Test Lab, das über 150 Gerätemodelle abdeckt.
Die lebenszyklusabhängige Bindung eliminiert manuelles Ressourcenmanagement. Camera2 erfordert explizite Open/Close-Aufrufe, die zu Leaks führen, wenn sie nicht in jedem Lifecycle-Callback korrekt behandelt werden.
Wie bindet CameraProvider Use Cases an den Lebenszyklus?
CameraProvider verwendet intern das LifecycleObserver-Pattern. Beim Aufruf von bindToLifecycle() registriert es einen Observer am bereitgestellten LifecycleOwner. Dieser Observer empfängt ON_START- und ON_STOP-Events zum Öffnen und Schließen der Kamera.
Die Schlüsselerkenntnis: CameraX startet die Kamera nicht sofort beim Binden. Es wartet, bis der Lebenszyklus den STARTED-Zustand erreicht, was dem Timing von Activity.onStart() entspricht.
Was passiert beim Binden inkompatibler Use Cases?
Nicht alle Use-Case-Kombinationen funktionieren auf allen Geräten. Preview + VideoCapture + ImageAnalysis + ImageCapture kann auf älterer Hardware fehlschlagen. CameraX wirft eine IllegalArgumentException zur Bind-Zeit, nicht zur Laufzeit.
Die Lösung besteht darin, CameraProvider.hasCamera() und Gerätefähigkeiten zu prüfen, bevor komplexe Kombinationen gebunden werden. Für kritische Apps sollte explizit auf Low-End-Geräten getestet werden.
Den Unterschied zwischen CAPTURE_MODE_MINIMIZE_LATENCY und CAPTURE_MODE_MAXIMIZE_QUALITY erklären
MINIMIZE_LATENCY reduziert die Auslöseverzögerung durch schnellere Verarbeitungspipelines, möglicherweise unter Überspringen einiger Nachbearbeitung. MAXIMIZE_QUALITY wendet vollständige HDR+-Verarbeitung, Rauschunterdrückung und Multi-Frame-Aufnahme auf unterstützten Geräten an.
Der Kompromiss: Latenz-Modus erfasst in 100-200ms, Qualitätsmodus kann 500ms-1s dauern, abhängig von der Beleuchtung. Social Apps wählen typischerweise Latenz. Dokumentenscanner-Apps wählen Qualität.
Wie handhabt CameraX Geräterotation?
CameraX handhabt Rotation automatisch durch die Zielrotations-Einstellung. Standardmäßig verwendet es die Display-Rotation, aber Apps können mit setTargetRotation() überschreiben. Die EXIF-Daten des Ausgabebilds enthalten das korrekte Orientierungs-Tag.
Für PreviewView handhabt der scaleType Seitenverhältnis-Unterschiede. FILL_CENTER beschneidet zum Füllen, FIT_CENTER zeigt Letterboxing. Die Wahl hängt davon ab, ob die App Vollbild-Vorschau oder Vermeidung von Beschneidung priorisiert.
Abhängigkeiten und Setup für CameraX 1.6
Die CameraX-Bibliothek ist in mehrere Artefakte aufgeteilt. Es sollte nur eingebunden werden, was die App verwendet, um die APK-Größe zu minimieren.
dependencies {
val cameraxVersion = "1.6.2"
// Core-Bibliothek für alle Use Cases erforderlich
implementation("androidx.camera:camera-core:$cameraxVersion")
// Camera2-Implementierung (erforderlich)
implementation("androidx.camera:camera-camera2:$cameraxVersion")
// Lifecycle-Integration
implementation("androidx.camera:camera-lifecycle:$cameraxVersion")
// VideoCapture Use Case
implementation("androidx.camera:camera-video:$cameraxVersion")
// PreviewView und Kamera-UI-Komponenten
implementation("androidx.camera:camera-view:$cameraxVersion")
// Optional: Extensions (Nachtmodus, HDR, etc.)
implementation("androidx.camera:camera-extensions:$cameraxVersion")
// Optional: Echtzeit-Effekte
implementation("androidx.camera:camera-effects:$cameraxVersion")
}
android {
// CameraX erfordert Java 11 Bytecode
compileOptions {
sourceCompatibility = JavaVersion.VERSION_11
targetCompatibility = JavaVersion.VERSION_11
}
}Das Manifest benötigt Feature-Deklarationen und Berechtigungen:
<!-- AndroidManifest.xml -->
<manifest>
<!-- Kamera-Hardware-Anforderung -->
<uses-feature android:name="android.hardware.camera.any" />
<!-- Laufzeit-Berechtigungen -->
<uses-permission android:name="android.permission.CAMERA" />
<uses-permission android:name="android.permission.RECORD_AUDIO" />
</manifest>Verwandte Muster für Kotlin Coroutines gelten beim Wrapping von CameraX ListenableFuture-Aufrufen in Suspend-Funktionen.
Fang an zu üben!
Teste dein Wissen mit unseren Interview-Simulatoren und technischen Tests.
Was CameraX 1.6 für Produktions-Apps ändert
CameraX 1.6 brachte drei Änderungen, die bestehende Implementierungen betreffen:
-
CameraPipe-Backend: Der interne Kamera-Stack verwendet jetzt CameraPipe, dieselbe Architektur wie die Pixel-Kamera. Dies verbessert die Leistung auf Pixel-Geräten und bietet eine sauberere Grundlage für erweiterte Funktionen. Bestehender Code muss nicht geändert werden.
-
Media3 Muxer Standard: VideoCapture verwendet jetzt standardmäßig Media3 Muxer anstelle von MediaMuxer. Dies verbessert die Absturz-Resilienz: Wenn die App während der Aufnahme terminiert, bleibt die Videodatei abspielbar. Die API-Oberfläche ist unverändert.
-
SessionConfig API stabil: Apps können jetzt erweiterte Kameraeinstellungen über SessionConfig ohne experimentelle Annotationen konfigurieren. Dies ermöglicht Funktionen wie gleichzeitige Nutzung von Front- und Rückkamera auf unterstützten Geräten.
Migrationspfad: Die Dependency-Version aktualisieren. Auf Geräten testen, die zuvor Probleme hatten. Die CameraX Release Notes dokumentieren Verhaltensänderungen zwischen Versionen.
- CameraX verwendet lebenszyklusabhängige Bindung:
bindToLifecycle()verbindet Use Cases sowohl mit der Kamera als auch mit dem Activity-Lebenszyklus - ImageCapture-Modi tauschen Latenz gegen Qualität: Wahl basierend auf Use Case, nicht Gerätefähigkeit
- VideoCapture erfordert Recorder-Setup vor dem Binden: Output-Optionen vor dem Start vorbereiten
- Berechtigungsbehandlung sollte den Zweck vor der Anfrage erklären: reduziert Ablehnungsraten
- CameraX 1.6 migrierte intern zu CameraPipe: keine API-Änderungen erforderlich, aber auf Zielgeräten testen
- Interview-Fragen fokussieren auf Lifecycle-Management, Use-Case-Kombinationen und Camera2-Vergleich
Findest du den Bug in Android?
Ein echter Codeausschnitt, ein versteckter Bug, ein Versuch pro Tag. Zum Ausprobieren ohne Konto.

Geschrieben von
Anthony Fillion-MailletGründer von SharpSkill
Seit über 10 Jahren Fullstack-Entwickler. Er leitet SharpSkill und verantwortet alles, was hier erscheint.
Aktualisiert am 11. September 2026
Teilen
Verwandte Artikel

Android Modularisierung 2026: Multi-Modul-Architektur und Interview-Fragen
Best Practices für Android Modularisierung mit Convention Plugins, Gradle Version Catalogs und Feature-Modulen. Inklusive Interview-Fragen für Senior-Entwickler.

Jetpack Navigation Compose 2026: Typsichere Navigation und Interviewfragen
Ein umfassender Leitfaden zur typsicheren Navigation mit Jetpack Compose. Mit praktischen Codebeispielen, Best Practices und häufigen Interviewfragen für Android-Entwickler.

Android WorkManager 2026: Hintergrundaufgaben, Constraints und Interview-Fragen
Umfassende Anleitung zu Android WorkManager 2.11/2.12 mit Kotlin-Codebeispielen, Constraints-Konfiguration, Verkettung von Arbeitsaufträgen und häufigen Fragen aus technischen Vorstellungsgesprächen.