部分红米设备出现RuntimeException: setParameters失败问题求助
我之前在适配红米系列设备的相机功能时,也碰到过一模一样的setParameters failed异常,踩了不少坑,来帮你拆解下原因和可行的解决方案:
异常原因分析
红米设备出现这个问题,大多是因为旧版MIUI的相机框架对参数限制比较严格,常见的触发点有这几个:
- 焦点模式不兼容:部分老款红米机型(比如早期红米Note系列)不支持
FOCUS_MODE_CONTINUOUS_PICTURE,强行设置就会直接抛出参数错误。 - 尺寸选择逻辑不合理:你直接取
getSupportedPictureSizes()的第一个元素,这个列表的排序规则在不同设备上不一致,而且很多红米设备要求预览尺寸和拍照尺寸的宽高比必须一致,否则会触发参数冲突。 - 旋转参数搭配冲突:
setDisplayOrientation和setRotation的设置顺序或数值不匹配,在低版本MIUI上容易触发校验失败。 - 参数设置顺序不符合设备要求:有些机型对参数设置的先后顺序有严格要求,比如必须先设置格式再设置尺寸,反过来就会报错。
针对性解决方案
1. 先校验焦点模式是否支持
不要直接硬编码设置焦点模式,先获取设备支持的列表再做判断,不支持就降级到通用模式:
List<String> supportedFocusModes = mParameters.getSupportedFocusModes(); if (supportedFocusModes.contains(Camera.Parameters.FOCUS_MODE_CONTINUOUS_PICTURE)) { mParameters.setFocusMode(Camera.Parameters.FOCUS_MODE_CONTINUOUS_PICTURE); } else { // 降级到兼容性更好的自动对焦模式 mParameters.setFocusMode(Camera.Parameters.FOCUS_MODE_AUTO); }
2. 合理选择拍照/预览尺寸
避免直接取第一个尺寸,优先选择和屏幕宽高比匹配的尺寸,同时保证预览和拍照尺寸比例一致:
// 先定义目标宽高比(这里以主流的16:9为例) float targetRatio = 16.0f / 9.0f; Camera.Size optimalPicSize = null; float minDiff = Float.MAX_VALUE; // 遍历支持的拍照尺寸,筛选最接近目标比例的 for (Camera.Size size : mParameters.getSupportedPictureSizes()) { float ratio = (float) size.width / size.height; // 允许0.1的比例误差 if (Math.abs(ratio - targetRatio) > 0.1) continue; if (Math.abs(size.height - getResources().getDisplayMetrics().heightPixels) < minDiff) { optimalPicSize = size; minDiff = Math.abs(size.height - getResources().getDisplayMetrics().heightPixels); } } // 如果没找到符合比例的,退而求其次取第一个 if (optimalPicSize == null) { optimalPicSize = mParameters.getSupportedPictureSizes().get(0); } // 设置拍照尺寸 mParameters.setPictureSize(optimalPicSize.width, optimalPicSize.height); // 别忘了同步设置预览尺寸(关键!很多红米设备要求两者比例一致) Camera.Size optimalPreviewSize = findOptimalSize(mParameters.getSupportedPreviewSizes(), targetRatio); mParameters.setPreviewSize(optimalPreviewSize.width, optimalPreviewSize.height); // 这里把重复的尺寸筛选逻辑抽成方法 private Camera.Size findOptimalSize(List<Camera.Size> sizes, float targetRatio) { Camera.Size optimalSize = null; float minDiff = Float.MAX_VALUE; for (Camera.Size size : sizes) { float ratio = (float) size.width / size.height; if (Math.abs(ratio - targetRatio) > 0.1) continue; if (Math.abs(size.height - getResources().getDisplayMetrics().heightPixels) < minDiff) { optimalSize = size; minDiff = Math.abs(size.height - getResources().getDisplayMetrics().heightPixels); } } return optimalSize != null ? optimalSize : sizes.get(0); }
3. 调整旋转参数的设置逻辑
不要直接硬设90度,要根据设备的实际旋转角度和相机朝向动态计算,避免参数冲突:
// 先获取相机信息和屏幕旋转角度 Camera.CameraInfo cameraInfo = new Camera.CameraInfo(); Camera.getCameraInfo(Camera.CameraInfo.CAMERA_FACING_BACK, cameraInfo); int screenRotation = getWindowManager().getDefaultDisplay().getRotation(); // 计算需要设置的旋转角度 int degrees = 0; switch (screenRotation) { case Surface.ROTATION_0: degrees = 0; break; case Surface.ROTATION_90: degrees = 90; break; case Surface.ROTATION_180: degrees = 180; break; case Surface.ROTATION_270: degrees = 270; break; } int displayOrientation; if (cameraInfo.facing == Camera.CameraInfo.CAMERA_FACING_FRONT) { displayOrientation = (cameraInfo.orientation + degrees) % 360; displayOrientation = (360 - displayOrientation) % 360; // 前置相机需要镜像补偿 } else { displayOrientation = (cameraInfo.orientation - degrees + 360) % 360; } // 先设置显示方向,再同步设置图片旋转参数 camera.setDisplayOrientation(displayOrientation); mParameters.setRotation(displayOrientation);
4. 用try-catch包裹参数设置逻辑
即使做了所有校验,个别机型还是可能有特殊情况,所以一定要加异常捕获,避免崩溃:
try { camera.setParameters(mParameters); } catch (RuntimeException e) { e.printStackTrace(); // 恢复到相机默认参数,再尝试设置基础参数 mParameters = camera.getParameters(); try { mParameters.setPictureFormat(PixelFormat.JPEG); mParameters.setJpegQuality(85); camera.setParameters(mParameters); } catch (RuntimeException ex) { ex.printStackTrace(); // 极端情况,提示用户相机初始化失败 Toast.makeText(this, "相机初始化失败,请检查相机权限", Toast.LENGTH_SHORT).show(); } }
额外建议
如果你们的项目兼容Android 5.0及以上版本,优先使用Camera2 API替代旧的Camera API——旧API已经停止维护,红米新机型对Camera2的支持更好,兼容性问题会少很多。
内容的提问来源于stack exchange,提问作者SHA
相关产品推荐
相关产品推荐

