Android Coden
Android 4 min lesen

Kamera-Grundlagen mit CameraX

CameraX vereinfacht den geräteübergreifenden Kamerazugriff auf Android. Du lernst Preview und Capture mit der offiziellen Jetpack-Bibliothek.

Die Kamera gehört zu den meistgenutzten Hardware-Komponenten auf Android-Geräten. Ob Foto-App, QR-Scanner oder Augmented-Reality-Feature – wer auf Kamerafunktionen zugreift, steht schnell vor einem Berg herstellerspezifischer Unterschiede. CameraX, ein Teil von Jetpack, löst dieses Problem durch eine einheitliche API, die über Hunderte von Gerätemodellen und API-Leveln zuverlässig funktioniert.

Was ist das?

CameraX ist eine Jetpack-Bibliothek, die eine konsistente Kamera-API für Android bereitstellt. Sie abstrahiert die Komplexität der darunterliegenden Camera2-API und macht Kamerazugriff geräteunabhängig. Statt plattformnaher Callbacks und gerätespezifischer Workarounds arbeitest du mit klaren UseCase-Abstraktionen: Preview für die Live-Vorschau, ImageCapture für Einzelaufnahmen, VideoCapture für Videoaufzeichnungen und ImageAnalysis für die Echtzeit-Bildauswertung.

CameraX ist in Phase 9 der Android-Roadmap verortet – dem Abschnitt „Platform APIs and Device Capabilities”. Das ist kein Zufall: Kamera-Code greift auf tiefer liegende Plattform-Funktionen zu, die du erst dann sicher einsetzt, wenn du Jetpack-Architektur, Lifecycle-Management und das Berechtigungssystem bereits verstehst. Ohne diese Grundlagen liefert jede Kamera-Integration früher oder später schwer reproduzierbare Fehler auf bestimmten Geräten.

Wie funktioniert es?

Das Herzstück von CameraX ist der ProcessCameraProvider. Er verwaltet die Kamera-Ressource für den gesamten Prozess und kümmert sich darum, die Kamera zu öffnen, zu konfigurieren und wieder freizugeben. Du fragst ihn über eine ListenableFuture an und erhältst ihn, sobald die Kamera bereit ist.

Der entscheidende Schritt ist bindToLifecycle: Du übergibst einen LifecycleOwner – typischerweise die Activity oder das Fragment – und CameraX beendet die Kamera automatisch, wenn der Owner seinen Lifecycle beendet. Damit vermeidest du Resource-Leaks, die bei direktem Camera2-Zugriff häufig auftreten, weil Entwickler das manuelle Schließen vergessen.

Jeder UseCase konfiguriert einen Aspekt der Kamera unabhängig voneinander:

  • Preview rendert das Live-Bild auf ein PreviewView-Widget in deiner UI.
  • ImageCapture löst eine hochauflösende Aufnahme aus und schreibt sie in eine Datei oder einen In-Memory-Buffer.
  • ImageAnalysis liefert jeden Frame als ImageProxy an einen Analyzer-Callback – ideal für ML Kit oder OpenCV.

Bevor du irgendeinen UseCase bindest, musst du die CAMERA-Berechtigung eingeholt haben. Android fordert diese zur Laufzeit; ohne sie wirft bindToLifecycle eine CameraAccessException. Nutze die Activity Result API mit registerForActivityResult statt des veralteten onRequestPermissionsResult-Musters, da letzteres in modernem Jetpack-Code als Antipattern gilt.

In der Praxis

Der folgende Code zeigt eine minimale CameraX-Integration mit Preview und ImageCapture in einer Compose-basierten Activity:

@Composable
fun CameraScreen() {
    val context = LocalContext.current
    val lifecycleOwner = LocalLifecycleOwner.current
    val previewView = remember { PreviewView(context) }

    val cameraPermission = rememberLauncherForActivityResult(
        ActivityResultContracts.RequestPermission()
    ) { granted ->
        if (!granted) {
            // Hinweis anzeigen, dass die App ohne Berechtigung nicht funktioniert
        }
    }

    LaunchedEffect(Unit) {
        cameraPermission.launch(Manifest.permission.CAMERA)
    }

    LaunchedEffect(previewView) {
        val cameraProvider = ProcessCameraProvider.getInstance(context).await()

        val preview = Preview.Builder().build().also {
            it.setSurfaceProvider(previewView.surfaceProvider)
        }

        val imageCapture = ImageCapture.Builder()
            .setCaptureMode(ImageCapture.CAPTURE_MODE_MINIMIZE_LATENCY)
            .build()

        cameraProvider.unbindAll()
        cameraProvider.bindToLifecycle(
            lifecycleOwner,
            CameraSelector.DEFAULT_BACK_CAMERA,
            preview,
            imageCapture
        )
    }

    AndroidView(factory = { previewView }, modifier = Modifier.fillMaxSize())
}

Stolperfalle: unbindAll vergessen

Ein typischer Anfängerfehler ist es, unbindAll() vor bindToLifecycle wegzulassen. Wenn du UseCases mehrfach bindest – zum Beispiel nach einem Orientierungswechsel oder nach dem erneuten Navigieren zum Screen – ohne vorher zu lösen, riskierst du eine IllegalArgumentException oder eine doppelt belegte Kamera-Ressource. Ruf immer cameraProvider.unbindAll() auf, bevor du neue UseCases bindest.

Eine zweite häufige Falle betrifft die Berechtigungslogik im Zusammenspiel mit der Data Layer: Speichere den Berechtigungsstatus nicht dauerhaft in einem Repository, sondern frage ihn über ContextCompat.checkSelfPermission immer zur Laufzeit ab. Nutzer können die Berechtigung in den Systemeinstellungen jederzeit entziehen, und ein veralteter gecachter Status führt zu Crashes oder stillen Fehlern.

Fazit

CameraX nimmt dir die gerätespezifische Kleinarbeit ab und gibt dir stattdessen klare Abstraktionen, die eng mit dem Android-Lifecycle verzahnt sind. Das Wichtigste in der Praxis: Verstehe das UseCase-Modell, handhabe Berechtigungen korrekt über die Activity Result API und teste ausschließlich auf echter Hardware. Baue jetzt eine einfache Kamera-App, die eine Aufnahme speichert, und beobachte im Android Studio Profiler, wie CameraX Ressourcen öffnet und freigibt – diese direkte Beobachtung schärft dein Verständnis nachhaltiger als jede Dokumentation.

Quellen (2)
Redaktion

Geschrieben von

Redaktion

Das Redaktionsteam recherchiert und schreibt Artikel zu aktuellen Themen rund um Tech, Lifestyle und Ratgeber.