如何使用 CameraX 实现自动对焦和闪光灯控制?

解读

国内面试中,CameraX 已取代旧 Camera/Camera2 成为“必考题”。面试官不仅要求“能跑起来”,更关注“是否理解 API 背后的生命周期、线程模型与兼容性细节”。自动对焦与闪光灯是高频刚需场景,回答时要体现三点:

  1. 生命周期感知:CameraX 绑定 LifecycleOwner,自动开关相机,避免内存泄漏。
  2. 兼容性兜底:国产机型 ROM 碎片化严重,需用 CameraControl 的 ListenableFuture 做异步失败重试。
  3. 性能与体验:对焦区域需跟随点击坐标做 MeteringPoint 转换;闪光灯模式切换要防止主线程卡顿,并兼容夜景/扫码等国内典型场景。

知识点

  1. CameraX 架构:UseCase(Preview/ImageAnalysis/ImageCapture)+ CameraSelector + LifecycleOwner。
  2. 对焦类型:AF-S(单次)、AF-C(连续)、AF-OFF;MeteringPoint 基于 TextureView/SurfaceView 坐标系转换。
  3. 闪光灯模式:ON、OFF、AUTO、TORCH;ImageCapture 与 Preview 的闪光灯设置相互独立。
  4. ListenableFuture:CameraX 所有 CameraControl 操作异步返回,需添加回调监听,避免阻塞主线程。
  5. 兼容性:华为、小米、OPPO 部分机型对 AF 区域支持不完整,需通过 Camera2Interop 降级到 CaptureRequest.CONTROL_AF_REGIONS。
  6. 权限:Android 13 后闪光灯需 android.permission.FLASHLIGHT,部分 ROM 还需厂商白名单,面试需提到“国内渠道包加权限声明”。
  7. 性能:连续对焦间隔 <250 ms 会触发部分机型温控降亮度,需做防抖节流。

答案

“在 CameraX 中实现自动对焦与闪光灯控制,我分五步完成:
第一步,绑定生命周期:
ProcessCameraProvider.getInstance(context).get() 拿到 provider 后,通过 provider.bindToLifecycle(lifecycleOwner, cameraSelector, preview, imageCapture) 完成绑定,确保页面销毁时相机自动释放,防止国产 ROM 后台驻留导致耗电。

第二步,获取 CameraControl:
Camera camera = provider.bindToLifecycle(...) 返回的 Camera 对象直接拿到 camera.getCameraControl(),所有对焦与闪光灯操作都通过它下发,避免再建 Camera2 Session。

第三步,实现点击对焦:
在 TextureView 上监听 onTouch,把 (x,y) 通过 MeteringPointFactory.createPoint(x, y) 转成 MeteringPoint,再构造 FocusMeteringAction.Builder.addPoint(point).build(),调用 cameraControl.startFocusAndMetering(action)。返回的 ListenableFuture 加回调:成功时给用户绿色对焦框,失败时捕获 FocusMeteringResult.isFocusSuccessful()==false,降级到 cameraControl.cancelFocusAndMetering() 并提示“手动对焦失败”。

第四步,连续对焦优化:
扫码场景需要 AF-C,通过 Camera2Interop.Extender(preview).setCaptureRequestOption(CaptureRequest.CONTROL_AF_MODE, CONTROL_AF_MODE_CONTINUOUS_PICTURE) 注入 Camera2 参数;同时监听 preview.onPreviewOutputUpdate(),若 500 ms 内未收到清晰帧,主动触发一次 startFocusAndMetering 做强制单次对焦,解决国产机连续对焦漂移问题。

第五步,闪光灯控制:
拍照前根据 UI 开关状态设置 imageCapture.setFlashMode(FlashMode.ON/OFF/AUTO);若需要手电筒常亮,调用 cameraControl.enableTorch(true),返回的 ListenableFuture 失败时捕获 TorchUnavailableException,提示“闪光灯被占用”。针对国内夜景模式,额外判断 camera.getCameraInfo().hasFlashUnit(),避免无闪光灯设备崩溃。

通过以上五步,可在生命周期安全、线程异步、机型兼容三个维度,稳定实现 CameraX 的自动对焦与闪光灯控制。”

拓展思考

  1. 对焦与曝光分离:国内高端机型支持 AE/AF Lock,可通过 Camera2Interop 注入 CONTROL_AE_LOCKCONTROL_AF_REGIONS 不同区域,实现“点按对焦、滑动曝光”的 Pro 模式。
  2. 零延时拍照:利用 setCaptureMode(ImageCapture.CAPTURE_MODE_MINIMIZE_LATENCY) 配合闪光灯,需预闪测光再主闪,避免红眼;此时要监听 takePictureOnImageCapturedCallbackImageProxy.getImageInfo().getFlashState(),判断照片是否真实触发闪光,防止国内用户投诉“开了闪光灯但照片黑”。
  3. 多摄像头切换:折叠屏手机前后摄共用同一屏幕,切换摄像头后需重新执行 startFocusAndMetering,因为 MeteringPoint 坐标系已变;可通过 CameraSelector.LENS_FACING_EXTERNAL 识别外屏摄像头,减少用户二次对焦。
  4. 权限沙盒:Android 13 隐私沙盒限制后台调用闪光灯,需在前台服务加 FOREGROUND_SERVICE_TYPE_CAMERA 并弹出厂商自定义提示,面试可补充“国内渠道 SDK 需接入小米/华为权限申请 API,否则应用市场审核被拒”。