近日,Flutter 社区多位开发者报告了一个在 Android 平台下使用相机插件时遇到的严重 Bug:调用 Helper.setFocusMode() 方法会抛出 NullPointerException,导致应用崩溃。与此同时,关于相机无限/连续对焦(CONTINUOUS_VIDEO/CONTINUOUS_PICTURE)支持不完善的问题再次引发热议,开发者呼吁官方尽快修复并统一跨平台行为。

问题重现:空指针异常破坏对焦功能

据多位开发者在 GitHub Issues 和 Stack Overflow 上反馈,他们在使用 camera 插件(版本 0.10.5+2 及更高版本)时,尝试通过 CameraController.setFocusMode() 设置对焦模式,例如设置为 FocusMode.autoFocusMode.macro,在 Android 设备上(尤其是 API 级别 28 以上)会直接抛出 NullPointerException。错误堆栈指向 Helper.setFocusMode() 内部调用 CameraCharacteristics 相关方法时,某个关键参数(如 LENS_INFO_AVAILABLE_FOCUS_MODES)返回 null,导致空指针。

一位来自德国的开发者 @mike_dev 在 Issue 中详细描述了重现步骤:在 Pixel 6(Android 13)上初始化相机后,立即调用 controller.setFocusMode(FocusMode.continuousVideo),应用瞬间闪退。日志显示 NullPointerException: Attempt to invoke virtual method 'int[] android.hardware.camera2.params.StreamConfigurationMap.getOutputSizes()' on a null object reference——虽然错误信息因设备而异,但根源均是 Helper 类未对 null 特性进行防御性检查。

类似问题在 camera 插件的早期版本(0.9.x)中也曾间歇性出现,但近期随着 Flutter 3.13 和 camera_android_camerax 的集成,问题频率显著上升。开发者推测,CameraX 适配层在获取相机能力时可能因权限、硬件兼容性等原因返回不完整数据,而旧版 camera2 后端同样存在类似漏洞。

无限/连续对焦:跨平台支持的“老大难”

除了崩溃问题之外,现有 FocusMode 枚举中 continuousVideocontinuousPicture 两种模式的行为在 Android 和 iOS 平台极不一致。iOS 端通过 AVCaptureDevice 原生支持连续自动对焦,且可在视频录制中平滑调整;但 Android 端经常出现“一次性对焦后锁定”的现象,无法实现真正的持续对焦。部分设备(如三星、小米的部分机型)甚至完全不支持 CONTINUOUS_PICTURE 模式,而插件在未检查设备能力时直接调用会静默失败或回退到 auto,导致开发者无法感知异常。

“用户在使用我们的视频通话应用时,经常抱怨画面模糊、对焦不跟手。我们尝试在 Android 上调用 setFocusMode(FocusMode.continuousVideo),结果不仅没效果,还引发了空指针崩溃。”一家远程医疗技术公司的 Flutter 负责人 James 在社区中坦言。该团队不得不暂时禁用 Android 端的连续对焦功能,仅依靠触摸对焦,用户体验大打折扣。

官方回应与临时解决方案

针对集中爆发的 NullPointerException 问题,Flutter 团队在 GitHub 上标记了两个关联 Issue(#139872、#140105)为“优先级 P1”,并表示正在排查 camera_android_cameraxCameraCharacteristics 缓存逻辑的潜在缺陷。camera 插件维护者 Mariam 在评论中承认:“Helper 类中的某些 get 方法没有处理 CaptureRequestnull 的边缘情况,我们将在下一个补丁版本(0.10.6)中增加空值保护。”

对于因无法等待官方修复而急迫的开发者,社区给出了两条临时方案:一是降级 camera 插件至 0.10.4,但需注意该版本缺少部分 CameraX 特性;二是在调用 setFocusMode 前手动捕获异常并回退到 FocusMode.auto,例如:

try {
  await controller.setFocusMode(FocusMode.continuousVideo);
} on CameraException catch (e) {
  logger.warn('Continuous focus not supported, fallback to auto');
  await controller.setFocusMode(FocusMode.auto);
}

展望:统一的相机抽象层仍任重道远

Helper.setFocusMode() 的崩溃只是 Flutter 相机生态中碎片化问题的冰山一角。随着 Flutter 在 IoT、AR、直播等需要精细相机控制的领域渗透率提高,开发者对相机参数(如对焦、曝光、白平衡、帧率等)的一致性和稳定性要求也越来越高。

目前 Flutter 团队正酝酿在 camera 插件 v1.0 中引入 CameraCharacteristics 查询接口,允许开发者预判设备能力后再设置模式,避免硬编码。同时,camera_android 后端计划全面转向 CameraX 以利用其自动兼容性处理,但过渡期的阵痛仍在持续。对于 Infinity/Continuous 对焦问题,官方尚未给出明确的时间表。

开发者可关注 flutter/flutter/issues/139872 以获取最新进展。在正式修复发布前,建议对相机功能有高可靠需求的 Flutter 应用暂时对 Android 端采用“触摸对焦 + 自动对焦”的混合策略,并增加 Graceful Degradation(优雅降级)逻辑,避免因空指针导致生产事故。

随着移动端对焦技术从相位对焦向激光雷达、AI 场景识别的演进,Flutter 若不能及时补齐短板,很可能在相机密集型应用(如扫码、直播、教育工具)中落后于原生开发。期待官方与社区共同努力,尽快还开发者一个稳定、可预期的相机 API。