Lensa dan kemampuan kamera

Catatan: Halaman ini merujuk ke paket Camera2. Kecuali jika aplikasi Anda memerlukan fitur level rendah tertentu dari Camera2, sebaiknya gunakan CameraX. CameraX dan Camera2 mendukung Android 5.0 (level API 21) dan versi yang lebih baru.

Banyak perangkat Android modern memiliki dua kamera atau lebih di bagian depan, belakang, atau kedua sisi perangkat. Setiap lensa dapat memiliki kemampuan unik, seperti pengambilan gambar burst, kontrol manual, atau pelacakan gerakan. Aplikasi untuk menyetorkan cek mungkin hanya menggunakan kamera belakang pertama, sedangkan aplikasi media sosial mungkin secara default menggunakan kamera depan, tetapi memberi pengguna opsi untuk beralih di antara semua lensa yang tersedia. AI juga dapat mengingat pilihan mereka.

Halaman ini membahas cara mencantumkan lensa kamera dan kemampuannya sehingga Anda dapat membuat keputusan dalam aplikasi tentang lensa yang akan digunakan dalam situasi tertentu. Cuplikan kode berikut mengambil daftar semua kamera dan melakukan iterasi pada kamera tersebut:

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) }
    // ...
}

Variabel cameraLensFacing menjelaskan arah hadap kamera relatif terhadap layar perangkat, dan memiliki salah satu nilai berikut:

Untuk mengetahui informasi selengkapnya tentang konfigurasi arah lensa, lihat CameraCharacteristics.LENS_FACING.

Variabel cameraCapabilities dari contoh kode sebelumnya berisi informasi tentang berbagai kemampuan, termasuk apakah kamera dapat menghasilkan frame standar sebagai output (bukan, misalnya, hanya data sensor kedalaman). Anda dapat mencari apakah CameraMetadata.REQUEST_AVAILABLE_CAPABILITIES_BACKWARD_COMPATIBLE adalah salah satu kemampuan kamera yang tercantum, yang disimpan sebagai flag di isBackwardCompatible.

Memilih setelan default yang sesuai

Di aplikasi, Anda mungkin ingin membuka kamera tertentu secara default (jika tersedia). Misalnya, aplikasi selfie kemungkinan akan membuka kamera depan, sedangkan aplikasi augmented reality mungkin akan memulai dengan kamera belakang. Fungsi berikut menampilkan kamera pertama yang menghadap ke arah tertentu:

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) }
        return null
    }
}

Mengaktifkan pengalihan kamera

Banyak aplikasi kamera memberi pengguna opsi untuk beralih antarkamera:

Antarmuka aplikasi Google Kamera yang menampilkan tombol ganti kamera.
Gambar 1. Tombol ganti kamera di aplikasi Google Kamera

Banyak perangkat memiliki beberapa kamera yang menghadap ke arah yang sama. Beberapa bahkan memiliki kamera USB eksternal. Untuk memberi pengguna UI yang memungkinkan mereka beralih di antara kamera yang menghadap ke arah yang berbeda, pilih kamera pertama yang tersedia untuk setiap kemungkinan konfigurasi arah lensa.

Meskipun tidak ada logika universal untuk memilih kamera berikutnya, kode berikut berfungsi untuk sebagian besar kasus penggunaan:

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)
    }
}

Kode ini berfungsi untuk banyak perangkat dengan berbagai konfigurasi. Untuk mengetahui informasi selengkapnya tentang cara memperhitungkan kasus ekstrem, lihat CameraMetadata.REQUEST_AVAILABLE_CAPABILITIES_LOGICAL_MULTI_CAMERA.

Membuat aplikasi yang kompatibel

Untuk aplikasi yang masih menggunakan Camera API yang tidak digunakan lagi, jumlah kamera yang ditampilkan Camera.getNumberOfCameras() bergantung pada implementasi OEM. Jika ada multi-kamera logis dalam sistem, untuk mempertahankan kompatibilitas mundur aplikasi, metode ini hanya akan mengekspos satu kamera untuk setiap kamera logis dan grup kamera fisik yang mendasarinya. Gunakan Camera2 API untuk melihat semua kamera.

Untuk mengetahui informasi latar belakang selengkapnya tentang orientasi kamera, lihat Camera.CameraInfo.orientation.

Secara umum, gunakan API Camera.getCameraInfo() untuk mengkueri semua orientation kamera, dan hanya mengekspos satu kamera untuk setiap orientasi yang tersedia bagi pengguna yang beralih antar-kamera.

Mendukung semua jenis perangkat

Jangan berasumsi bahwa aplikasi Anda selalu berjalan di perangkat genggam dengan satu atau dua kamera. Sebagai gantinya, pilih kamera yang paling sesuai untuk aplikasi. Jika Anda tidak memerlukan kamera tertentu, pilih kamera pertama yang menghadap ke arah yang dipilih. Jika kamera yang menghadap ke arah tertentu tidak tersedia, pertimbangkan apakah pengguna dapat menyelesaikan perjalanannya dengan kamera lain. Jangan membatasi ketersediaan aplikasi Anda di perangkat tertentu berdasarkan hardware kamera. Jika kamera eksternal terhubung, pengguna mungkin lebih memilihnya sebagai default.