如何在Android多摄像头设备中获取指定摄像头ID
多摄像头设备指定摄像头ID选择方案
你的代码当前遍历所有后置摄像头,但每次循环都会覆盖cameraId变量,最终只保留最后一个遍历到的摄像头ID——而超广角摄像头通常是遍历顺序的最后一个,所以才会只拿到它。要精准选择目标摄像头,可通过摄像头的硬件特性来筛选,以下是两种实用方法:
方法1:按等效焦距筛选
不同类型的摄像头等效焦距不同:主摄一般在24mm左右,超广角约16mm,长焦则在50mm以上。通过CameraCharacteristics.LENS_INFO_AVAILABLE_FOCAL_LENGTHS获取焦距,匹配目标即可:
private fun setupCamera(targetFocalLength: Float) { val cameraIds: Array<String> = cameraManager.cameraIdList for (id in cameraIds) { val cameraCharacteristics = cameraManager.getCameraCharacteristics(id) // 跳过前置摄像头 if (cameraCharacteristics.get(CameraCharacteristics.LENS_FACING) == CameraCharacteristics.LENS_FACING_FRONT) { continue } // 获取该摄像头的可用焦距数组 val focalLengths = cameraCharacteristics.get(CameraCharacteristics.LENS_INFO_AVAILABLE_FOCAL_LENGTHS) focalLengths?.let { // 允许微小误差,适配硬件参数偏差 if (it.any { fl -> Math.abs(fl - targetFocalLength) < 0.1f }) { val streamConfigurationMap = cameraCharacteristics.get(CameraCharacteristics.SCALER_STREAM_CONFIGURATION_MAP) streamConfigurationMap?.let { scm -> previewSize = scm.getOutputSizes(ImageFormat.JPEG).maxByOrNull { it.height * it.width }!! imageReader = ImageReader.newInstance( previewSize.width, previewSize.height, ImageFormat.JPEG, 1 ) initPreview() imageReader.setOnImageAvailableListener(onImageAvailableListener, backgroundHandler) cameraId = id // 找到目标后直接跳出循环,避免被后续摄像头覆盖 return@setupCamera } } } } }
调用示例:选主摄传24.0f,选超广角传16.0f。不确定参数的话,可先打印所有摄像头的焦距值确认。
方法2:按摄像头能力标识筛选
部分设备会通过CameraCharacteristics.REQUEST_AVAILABLE_CAPABILITIES标记摄像头类型,直接匹配对应标识即可:
private fun setupCamera(targetCapability: Int) { val cameraIds: Array<String> = cameraManager.cameraIdList for (id in cameraIds) { val cameraCharacteristics = cameraManager.getCameraCharacteristics(id) if (cameraCharacteristics.get(CameraCharacteristics.LENS_FACING) == CameraCharacteristics.LENS_FACING_FRONT) { continue } val capabilities = cameraCharacteristics.get(CameraCharacteristics.REQUEST_AVAILABLE_CAPABILITIES) capabilities?.let { if (it.contains(targetCapability)) { val streamConfigurationMap = cameraCharacteristics.get(CameraCharacteristics.SCALER_STREAM_CONFIGURATION_MAP) streamConfigurationMap?.let { scm -> previewSize = scm.getOutputSizes(ImageFormat.JPEG).maxByOrNull { it.height * it.width }!! imageReader = ImageReader.newInstance( previewSize.width, previewSize.height, ImageFormat.JPEG, 1 ) initPreview() imageReader.setOnImageAvailableListener(onImageAvailableListener, backgroundHandler) cameraId = id return@setupCamera } } } } }
常用能力标识:
CameraCharacteristics.REQUEST_AVAILABLE_CAPABILITIES_BACKWARD_COMPATIBLE:主摄CameraCharacteristics.REQUEST_AVAILABLE_CAPABILITIES_WIDE_ANGLE:超广角CameraCharacteristics.REQUEST_AVAILABLE_CAPABILITIES_TELEPHOTO:长焦
调用示例:选主摄就传入CameraCharacteristics.REQUEST_AVAILABLE_CAPABILITIES_BACKWARD_COMPATIBLE。
核心修正点
你原来的代码没有在找到目标摄像头后终止循环,导致后续遍历的摄像头会覆盖之前的cameraId——这是只拿到超广角的核心原因。现在的代码在匹配到目标后立即return@setupCamera,确保只保留选中的摄像头ID。
内容的提问来源于stack exchange,提问作者SadeQ digitALLife
相关产品推荐
相关产品推荐

