方案一:
调用 CameraManager
的 getCameraIdList()
方法来获取所有可用的相机 ID。 通过CameraCharacteristics
类来获取每个相机的特性,包括是否支持广角和超广角。(不一定获取的 到,部分厂商会屏蔽获取或返回空)
CameraManager cameraManager = (CameraManager) getSystemService(Context.CAMERA_SERVICE);
String[] cameraIdList = cameraManager.getCameraIdList();
for (String cameraId : cameraIdList) {
CameraCharacteristics characteristics = cameraManager.getCameraCharacteristics(cameraId);
if (characteristics.hasControls()) {
boolean supportsWideAngle = characteristics.getBoolean(CameraCharacteristics.LENS_INFO_AVAILABLE_APERTURES, false);
float maxWideAngleFNumber = characteristics.getFloat(CameraCharacteristics.LENS_INFO_AVAILABLE_APERTURES, 0);
float minWideAngleFNumber = characteristics.getFloat(CameraCharacteristics.LENS_INFO_AVAILABLE_APERTURES, 1);
float maxWideAngleFocalLength = characteristics.getFloat(CameraCharacteristics.LENS_INFO_AVAILABLE_FILTER_DENSITIES, 0);
float minWideAngleFocalLength = characteristics.getFloat(CameraCharacteristics.LENS_INFO_AVAILABLE_FILTER_DENSITIES, 1);
boolean supportsUltraWideAngle = characteristics.getBoolean(CameraCharacteristics.LENS_INFO_AVAILABLE_APERTURES, false);
float maxUltraWideAngleFNumber = characteristics.getFloat(CameraCharacteristics.LENS_INFO_AVAILABLE_APERTURES, 0);
float minUltraWideAngleFNumber = characteristics.getFloat(CameraCharacteristics.LENS_INFO_AVAILABLE_APERTURES, 1);
float maxUltraWideAngleFocalLength = characteristics.getFloat(CameraCharacteristics.LENS_INFO_AVAILABLE_FILTER_DENSITIES, 0);
float minUltraWideAngleFocalLength = characteristics.getFloat(CameraCharacteristics.LENS_INFO_AVAILABLE_FILTER_DENSITIES, 1);
if (supportsWideAngle) {
// 广角镜头支持
Log.d("Camera", "支持广角镜头,最大光圈 F" + maxWideAngleFNumber + ",最小光圈 F" + minWideAngleFNumber + ",最大焦距 " + maxWideAngleFocalLength + "mm,最小焦距 " + minWideAngleFocalLength + "mm");
}
if (supportsUltraWideAngle) {
// 超广角镜头支持
Log.d("Camera", "支持超广角镜头,最大光圈 F" + maxUltraWideAngleFNumber + ",最小光圈 F" + minUltraWideAngleFNumber + ",最大焦距 " + maxUltraWideAngleFocalLength + "mm,最小焦距 " + minUltraWideAngleFocalLength + "mm");
}
}
}
方案二:
手动计算相机镜头FOV,该方案同样存在当厂商屏蔽掉获取传感器物理尺寸信息后无法拿到广角ID的问题
for (final String cameraId : cManager.getCameraIdList()) {
CameraCharacteristics characteristics = cManager.getCameraCharacteristics(cameraId);
int cOrientation = characteristics.get(CameraCharacteristics.LENS_FACING);
if (cOrientation == CameraCharacteristics.LENS_FACING_BACK) {
//防止调用异常相机ID,先判断参数是否能读取
StreamConfigurationMap streamConfigurationMap = characteristics.get(CameraCharacteristics.SCALER_STREAM_CONFIGURATION_MAP);
if (streamConfigurationMap == null || streamConfigurationMap.getOutputSizes(ImageFormat.JPEG) == null || streamConfigurationMap.getOutputSizes(SurfaceTexture.class) == null)
continue;
float[] maxFocus = characteristics.get(CameraCharacteristics.LENS_INFO_AVAILABLE_FOCAL_LENGTHS);
//某些机箱存在逻辑摄像头,多摄像头合一,存在多个焦距,取摄像头最大焦距做处理
float mFocus = maxFocus[0];
for (int i = 0; i < maxFocus.length; i++) {
mFocus = maxFocus[i] > mFocus ? maxFocus[i] : mFocus;
}
SizeF size = characteristics.get(CameraCharacteristics.SENSOR_INFO_PHYSICAL_SIZE);
float w = size.getWidth();
float h = size.getHeight();
horizonalAngle = (float) (2 * Math.atan(w / (mFocus * 2)));
verticalAngle = (float) (2 * Math.atan(h / (mFocus * 2)));
float fov = horizonalAngle * verticalAngle;
if (fov > maxFov) {
maxFov = fov;
mWideCameraId = Integer.parseInt(cameraId);
}
Log.d("Camera2", "calculateFOV horizonalAngle:" + horizonalAngle + " verticalAngle:" + verticalAngle);
}
}
具体原理可以搜索stackoverflow
方案三:
通过各家厂商的SDK针对性的获取广角/超光角功能,目前已经适配的包括华为(鸿蒙)、OV系,小米在开发者官网未找到相关文档,可以联系官方人员获取。三星目前可以通过方案二来获取,谷歌Pixel系列同理。