如何使用 CameraX 实现自动对焦和闪光灯控制?
解读
国内面试中,CameraX 已取代旧 Camera/Camera2 成为“必考题”。面试官不仅要求“能跑起来”,更关注“是否理解 API 背后的生命周期、线程模型与兼容性细节”。自动对焦与闪光灯是高频刚需场景,回答时要体现三点:
- 生命周期感知:CameraX 绑定 LifecycleOwner,自动开关相机,避免内存泄漏。
- 兼容性兜底:国产机型 ROM 碎片化严重,需用 CameraControl 的 ListenableFuture 做异步失败重试。
- 性能与体验:对焦区域需跟随点击坐标做 MeteringPoint 转换;闪光灯模式切换要防止主线程卡顿,并兼容夜景/扫码等国内典型场景。
知识点
- CameraX 架构:UseCase(Preview/ImageAnalysis/ImageCapture)+ CameraSelector + LifecycleOwner。
- 对焦类型:AF-S(单次)、AF-C(连续)、AF-OFF;MeteringPoint 基于 TextureView/SurfaceView 坐标系转换。
- 闪光灯模式:ON、OFF、AUTO、TORCH;ImageCapture 与 Preview 的闪光灯设置相互独立。
- ListenableFuture:CameraX 所有 CameraControl 操作异步返回,需添加回调监听,避免阻塞主线程。
- 兼容性:华为、小米、OPPO 部分机型对 AF 区域支持不完整,需通过 Camera2Interop 降级到 CaptureRequest.CONTROL_AF_REGIONS。
- 权限:Android 13 后闪光灯需 android.permission.FLASHLIGHT,部分 ROM 还需厂商白名单,面试需提到“国内渠道包加权限声明”。
- 性能:连续对焦间隔 <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 的自动对焦与闪光灯控制。”
拓展思考
- 对焦与曝光分离:国内高端机型支持 AE/AF Lock,可通过 Camera2Interop 注入
CONTROL_AE_LOCK与CONTROL_AF_REGIONS不同区域,实现“点按对焦、滑动曝光”的 Pro 模式。 - 零延时拍照:利用
setCaptureMode(ImageCapture.CAPTURE_MODE_MINIMIZE_LATENCY)配合闪光灯,需预闪测光再主闪,避免红眼;此时要监听takePicture的OnImageCapturedCallback里ImageProxy.getImageInfo().getFlashState(),判断照片是否真实触发闪光,防止国内用户投诉“开了闪光灯但照片黑”。 - 多摄像头切换:折叠屏手机前后摄共用同一屏幕,切换摄像头后需重新执行
startFocusAndMetering,因为 MeteringPoint 坐标系已变;可通过CameraSelector.LENS_FACING_EXTERNAL识别外屏摄像头,减少用户二次对焦。 - 权限沙盒:Android 13 隐私沙盒限制后台调用闪光灯,需在前台服务加
FOREGROUND_SERVICE_TYPE_CAMERA并弹出厂商自定义提示,面试可补充“国内渠道 SDK 需接入小米/华为权限申请 API,否则应用市场审核被拒”。