Kameraobjektive und Funktionen

Hinweis:Diese Seite bezieht sich auf das Camera2-Paket. Sofern für Ihre App keine spezifischen Low-Level-Funktionen von Camera2 erforderlich sind, empfehlen wir die Verwendung von CameraX. Sowohl CameraX als auch Camera2 unterstützen Android 5.0 (API-Level 21) und höher.

Viele moderne Android-Geräte haben zwei oder mehr Kameras auf der Vorder-, Rückseite auf beiden Seiten des Geräts. Jedes Objektiv hat besondere Funktionen, z. B. Bilderfolge, manuelle Steuerung oder Bewegungserkennung. Eine App zum Einzahlen von Schecks verwendet möglicherweise Kamera auf der Rückseite, während Social-Media-Apps Frontkamera. Der Nutzer kann jedoch zwischen allen verfügbaren Objektive. Er kann sich auch die Auswahl merken.

Auf dieser Seite erfahren Sie, wie Sie Kameraobjektive und deren Funktionen auflisten, damit Sie können in Ihrer App entscheiden, welches Objektiv Sie in einer bestimmten Situation verwenden möchten. Mit dem folgenden Code-Snippet wird eine Liste aller Kameras abgerufen sie:

Kotlin

try {
    val cameraIdList = cameraManager.cameraIdList // may be empty

    // iterate over available camera devices
    for (cameraId in cameraIdList) {
        val characteristics = cameraManager.getCameraCharacteristics(cameraId)
        val cameraLensFacing = characteristics.get(CameraCharacteristics.LENS_FACING)
        val cameraCapabilities = characteristics.get(CameraCharacteristics.REQUEST_AVAILABLE_CAPABILITIES)

        // check if the selected camera device supports basic features
        // ensures backward compatibility with the original Camera API
        val isBackwardCompatible = cameraCapabilities?.contains(
            CameraMetadata.REQUEST_AVAILABLE_CAPABILITIES_BACKWARD_COMPATIBLE) ?: false
        ...
    }
} catch (e: CameraAccessException) {
    e.message?.let { Log.e(TAG, it) }
    ...
}

Java

try {
    String[] cameraIdList = cameraManager.getCameraIdList(); // may be empty

    // iterate over available camera devices
    for (String cameraId : cameraIdList) {
        CameraCharacteristics characteristics = cameraManager.getCameraCharacteristics(cameraId);
        int cameraLensFacing = characteristics.get(CameraCharacteristics.LENS_FACING);
        int[] cameraCapabilities =
            characteristics.get(CameraCharacteristics.REQUEST_AVAILABLE_CAPABILITIES);

        // check if the selected camera device supports basic features
        // ensures backward compatibility with the original Camera API
        boolean isBackwardCompatible = false;
        for (int capability : cameraCapabilities) {
            if (capability == CameraMetadata.REQUEST_AVAILABLE_CAPABILITIES_BACKWARD_COMPATIBLE) {
                isBackwardCompatible = true;
                break;
            }
        }
        ...
    }
} catch (CameraAccessException e) {
    Log.e(TAG, e.getMessage());
    ...
}

Die Variable cameraLensFacing beschreibt die Richtung, in die die Kamera zeigt relativ zum Gerätebildschirm und hat einen der folgenden Werte:

Weitere Informationen zur objektivseitigen Konfiguration finden Sie unter CameraCharacteristics.LENS_FACING

Die Variable cameraCapabilities aus dem vorherigen Codebeispiel enthält Informationen zu weiteren Funktionen, wie z. B. ob die Kamera Standard-Frames als Ausgabe erstellen können (im Gegensatz zu Tiefensensordaten). Sie können prüfen, CameraMetadata.REQUEST_AVAILABLE_CAPABILITIES_BACKWARD_COMPATIBLE gehört zu den aufgeführten Funktionen der Kamera. Sie wird in den isBackwardCompatible.

Wähle sinnvolle Standardeinstellungen aus

Wahrscheinlich möchtest du in deiner App standardmäßig eine bestimmte Kamera öffnen (falls verfügbar). Eine Selfie-App öffnet wahrscheinlich die Frontkamera Kamera starten, während Augmented-Reality-Apps mit der Kamera auf der Rückseite beginnen. Die folgende Funktion gibt die erste Kamera zurück, die in eine bestimmte Richtung zeigt:

Kotlin

fun getFirstCameraIdFacing(cameraManager: CameraManager,
                           facing: Int = CameraMetadata.LENS_FACING_BACK): String? {
    try {
        // Get list of all compatible cameras
        val cameraIds = cameraManager.cameraIdList.filter {
            val characteristics = cameraManager.getCameraCharacteristics(it)
            val capabilities = characteristics.get(CameraCharacteristics.REQUEST_AVAILABLE_CAPABILITIES)
            capabilities?.contains(
                    CameraMetadata.REQUEST_AVAILABLE_CAPABILITIES_BACKWARD_COMPATIBLE) ?: false
        }

        // Iterate over the list of cameras and return the first one matching desired
        // lens-facing configuration
        cameraIds.forEach {
            val characteristics = cameraManager.getCameraCharacteristics(it)
            if (characteristics.get(CameraCharacteristics.LENS_FACING) == facing) {
                return it
            }
        }

        // If no camera matched desired orientation, return the first one from the list
        return cameraIds.firstOrNull()
    } catch (e: CameraAccessException) {
        e.message?.let { Log.e(TAG, it) }
    }
}

Java

public String getFirstCameraIdFacing(CameraManager cameraManager, @Nullable Integer facing) {
    if (facing == null) facing = CameraMetadata.LENS_FACING_BACK;
    String cameraId = null;

    try {
        // Get a list of all compatible cameras
        String[] cameraIdList = cameraManager.getCameraIdList();

        // Iterate over the list of cameras and return the first one matching desired
        // lens-facing configuration and backward compatibility
        for (String id : cameraIdList) {
            CameraCharacteristics characteristics = cameraManager.getCameraCharacteristics(id);
            int[] capabilities = characteristics.get(CameraCharacteristics.REQUEST_AVAILABLE_CAPABILITIES);
            for (int capability : capabilities) {
                if (capability == CameraMetadata.REQUEST_AVAILABLE_CAPABILITIES_BACKWARD_COMPATIBLE
                        && characteristics.get(CameraCharacteristics.LENS_FACING).equals(facing)) {
                    cameraId = id;
                    break;
                }
            }
        }

        // If no camera matches the desired orientation, return the first one from the list
        cameraId = cameraIdList[0];
    } catch (CameraAccessException e) {
        Log.e(TAG, "getFirstCameraIdFacing: " + e.getMessage());
    }

    return cameraId;
}

Kamerawechsel aktivieren

Bei vielen Kamera-Apps haben Nutzer die Möglichkeit, zwischen den Kameras zu wechseln:

<ph type="x-smartling-placeholder">
</ph>
Abbildung 1. Schaltfläche „Kamera wechseln“ in der Google Kamera App

Viele Geräte haben mehrere Kameras, die in die gleiche Richtung zeigen. Einige haben sogar externen USB-Kameras verwenden. Um Nutzern eine Benutzeroberfläche zur Verfügung zu stellen, die es ihnen ermöglicht, zwischen Kameras auf der Vorderseite haben, wählen Sie jeweils die erste verfügbare Kamera aus. mit dem Objektiv.

Obwohl es keine universelle Logik für die Auswahl der nächsten Kamera gibt, Der folgende Code funktioniert für die meisten Anwendungsfälle:

Kotlin

fun filterCompatibleCameras(cameraIds: Array<String>,
                            cameraManager: CameraManager): List<String> {
    return cameraIds.filter {
        val characteristics = cameraManager.getCameraCharacteristics(it)
        characteristics.get(CameraCharacteristics.REQUEST_AVAILABLE_CAPABILITIES)?.contains(
                CameraMetadata.REQUEST_AVAILABLE_CAPABILITIES_BACKWARD_COMPATIBLE) ?: false
    }
}

fun filterCameraIdsFacing(cameraIds: List<String>, cameraManager: CameraManager,
                          facing: Int): List<String> {
    return cameraIds.filter {
        val characteristics = cameraManager.getCameraCharacteristics(it)
        characteristics.get(CameraCharacteristics.LENS_FACING) == facing
    }
}

fun getNextCameraId(cameraManager: CameraManager, currCameraId: String? = null): String? {
    // Get all front, back and external cameras in 3 separate lists
    val cameraIds = filterCompatibleCameras(cameraManager.cameraIdList, cameraManager)
    val backCameras = filterCameraIdsFacing(
            cameraIds, cameraManager, CameraMetadata.LENS_FACING_BACK)
    val frontCameras = filterCameraIdsFacing(
            cameraIds, cameraManager, CameraMetadata.LENS_FACING_FRONT)
    val externalCameras = filterCameraIdsFacing(
            cameraIds, cameraManager, CameraMetadata.LENS_FACING_EXTERNAL)

    // The recommended order of iteration is: all external, first back, first front
    val allCameras = (externalCameras + listOf(
            backCameras.firstOrNull(), frontCameras.firstOrNull())).filterNotNull()

    // Get the index of the currently selected camera in the list
    val cameraIndex = allCameras.indexOf(currCameraId)

    // The selected camera may not be in the list, for example it could be an
    // external camera that has been removed by the user
    return if (cameraIndex == -1) {
        // Return the first camera from the list
        allCameras.getOrNull(0)
    } else {
        // Return the next camera from the list, wrap around if necessary
        allCameras.getOrNull((cameraIndex + 1) % allCameras.size)
    }
}

Java

public List<String> filterCompatibleCameras(CameraManager cameraManager, String[] cameraIds) {
    final List<String> compatibleCameras = new ArrayList<>();

    try {
        for (String id : cameraIds) {
            CameraCharacteristics characteristics = cameraManager.getCameraCharacteristics(id);
            int[] capabilities = characteristics.get(CameraCharacteristics.REQUEST_AVAILABLE_CAPABILITIES);
            for (int capability : capabilities) {
                if (capability == CameraMetadata.REQUEST_AVAILABLE_CAPABILITIES_BACKWARD_COMPATIBLE) {
                    compatibleCameras.add(id);
                }
            }
        }
    } catch (CameraAccessException e) {
        Log.e(TAG, "filterCompatibleCameras: " + e.getMessage());
    }

    return compatibleCameras;
}

public List<String> filterCameraIdsFacing(CameraManager cameraManager, List<String> cameraIds, int lensFacing) {
    final List<String> compatibleCameras = new ArrayList<>();

    try {
        for (String id : cameraIds) {
            CameraCharacteristics characteristics = cameraManager.getCameraCharacteristics(id);
            if (characteristics.get(CameraCharacteristics.LENS_FACING) == lensFacing) {
                compatibleCameras.add(id);
            }
        }
    } catch (CameraAccessException e) {
        Log.e(TAG, "filterCameraIdsFacing: " + e.getMessage());
    }

    return compatibleCameras;
}

public String getNextCameraId(CameraManager cameraManager, @Nullable String currentCameraId) {
    String nextCameraId = null;

    try {
        // Get all front, back, and external cameras in 3 separate lists
        List<String> compatibleCameraIds = filterCompatibleCameras(cameraManager, cameraManager.getCameraIdList());
        List<String> backCameras = filterCameraIdsFacing(cameraManager, compatibleCameraIds, CameraMetadata.LENS_FACING_BACK);
        List<String> frontCameras = filterCameraIdsFacing(cameraManager, compatibleCameraIds, CameraMetadata.LENS_FACING_FRONT);
        List<String>externalCameras = filterCameraIdsFacing(cameraManager, compatibleCameraIds, CameraMetadata.LENS_FACING_EXTERNAL);

        // The recommended order of iteration is: all external, first back, first front
        List<String> allCameras = new ArrayList<>(externalCameras);
        if (!backCameras.isEmpty()) allCameras.add(backCameras.get(0));
        if (!frontCameras.isEmpty()) allCameras.add(frontCameras.get(0));

        // Get the index of the currently selected camera in the list
        int cameraIndex = allCameras.indexOf(currentCameraId);

        // The selected camera may not be in the list, for example it could be an
        // external camera that has been removed by the user
        if (cameraIndex == -1) {
            // Return the first camera from the list
            nextCameraId = !allCameras.isEmpty() ? allCameras.get(0) : null;
        else {
            if (!allCameras.isEmpty()) {
                // Return the next camera from the list, wrap around if necessary
                nextCameraId = allCameras.get((cameraIndex + 1) % allCameras.size());
            }
        }
    } catch (CameraAccessException e) {
        Log.e(TAG, "getNextCameraId: " + e.getMessage());
    }

    return nextCameraId;
}

Dieser Code funktioniert für eine große Gruppe von Geräten mit vielen Konfigurationen. Weitere Informationen zur Berücksichtigung von Grenzfällen finden Sie unter CameraMetadata.REQUEST_AVAILABLE_CAPABILITIES_LOGICAL_MULTI_CAMERA.

Kompatible Apps erstellen

Bei Apps, die noch die eingestellte Camera API verwenden: die Anzahl der Kameras das Camera.getNumberOfCameras() hängt von der OEM-Implementierung ab. Befindet sich in der Ansicht eine logische Mehrfachkamera Um die Abwärtskompatibilität der App aufrechtzuerhalten, wird mit dieser Methode nur eine Kamera für jede logische Kamera und jede zugrunde liegende physische Kameragruppe. Verwende die Camera2 API, um alle Kameras zu sehen.

Weitere Hintergrundinformationen zur Ausrichtung der Kamera findest du unter Camera.CameraInfo.orientation

Verwenden Sie im Allgemeinen die Methode Camera.getCameraInfo() API zum Abfragen aller Kameras orientations, und setzen Sie nur eine Kamera für jede verfügbare Ausrichtung für Nutzende, zwischen Kameras wechseln.

Für alle Gerätetypen geeignet

Geht nicht davon aus, dass eure App immer auf einem Handheld-Gerät mit einem oder zwei Kameras. Wählen Sie stattdessen die am besten geeigneten Kameras für die App aus. Wenn Sie bestimmte Kamera benötigen, wählen Sie die erste Kamera aus, Richtung. Ist eine externe Kamera angeschlossen, könnten Sie davon ausgehen, bevorzugt.