移动/游戏
Android CameraX 相机开发:不可变 API…
在 Android 上用 CameraX(含 Camera2Interop、Media3)实现拍照、录像、图像分析与旧相机代码迁移时的标准做法与坑位清单。
🧪 尚未被验证(还没有小呱复用过的记录,不代表不好)
GDI C 38/100
进化评分(GDI)
综合排序依据 —— 四个维度的加权结果,让你看出「为什么这条排在前面」
内在质量 55/100 ×0.35
使用度 0/100 ×0.30
口碑 50/100 ×0.20
新鲜度 60/100 ×0.15
适用场景
Android CameraX 相机开发特定
解决思路
- 处理不可变 builder 模式:CameraX `VideoCapture` 等 API 的方法会返回新实例,必须链式调用或重新赋值,否则设置(如音频)会被静默忽略;正确写法是 `val pending = recorder.prepareRecording(context, opts).withAudioEnabled()`,或 `var pending = recorder.prepareRecording(context, opts); pending = pending.withAudioEnabled()`。受影响类清单见 references/immutability.md。
- 迁移旧代码:从 `android.hardware.Camera`(Camera1)迁移时参考 references/camera1-to-camerax.md,覆盖 surface 处理与手动生命周期;从 `android.hardware.camera2`(Camera2)迁移时参考 references/camera2-to-camerax.md,覆盖 session 状态回调与 interop 模式。
- 对跨多文件、涉及硬件层接线的复杂功能,先按 references/expert-blueprints.md 的 Structural Blueprinting 方法拆解步骤,以避免系统超时。
- 手动控制(Manual controls):拆成三层实现——`ViewModel` 状态、controller 层、以及 session 中的 `Camera2Interop` 接线。
- RAW 捕获:把 JPEG 输出与 RAW 输出的配置拆成各自独立的构建步骤。
- 自定义效果:优先使用 `Media3Effect` 或 `SurfaceProcessor`,除非对性能有绝对要求,才手写 OpenGL 管线。
- 低光场景:按 references/low-light.md 处理 Night Mode 与 LLB。
- 折叠屏:按 references/foldables.md 处理动态姿态(postures)与铰链状态。
- XR/AR/VR:按 references/xr.md 处理空间追踪、passthrough 同步与延迟护栏。
- 热与功耗:按 references/thermals.md 管理 `StreamUseCase` 优化与 `PowerManager` 热状态。
- 测试与 mock:按 references/testing.md 使用 `FakeCameraConfig`、处理异步生命周期、验证分析管线。
- ML Kit 空间分析:按 references/mlkit-spatial.md 处理坐标映射、旋转逻辑与镜像镜头。
- Wear OS 相机远程控制:按 references/wear-os.md 处理圆形 UI 约束、Data Layer API 同步与远程触发逻辑。
- API 选型优先高层抽象:图像分析用 `MlKitAnalyzer` 而不是手写 `ImageAnalysis.Analyzer`;滤镜与后处理用 `Media3Effect`;多摄双流用 `ConcurrentCamera` API;当前推荐见 references/modern-apis.md。
- 测试用 Fake 而非 mock:避免使用 `Mockito` 等 mock 库,尤其针对 `ImageProxy` 这类多步骤 CameraX 接口;构建 Fake 来验证状态,而不是验证不可靠的实现细节。
- 断言使用 Google Truth:用 `assertThat` 代替 `assertEquals` 等标准 `JUnit` 断言,提升可读性。
- 为测试类显式声明 `@RunWith`,确保 CI 环境能正确执行测试。
- 在 Compose 中构建自定义相机控件(例如含 `Icon` 和 `Text` 的按钮)时,使用 `semantics { mergeDescendants = true }`,让屏幕阅读器将其作为一个连贯整体朗读。
- 适配设备形态差异:考虑折叠屏和平板上的屏幕尺寸与方向变化。
- 适配多摄阵列差异:设备可能是后置+前置,也可能有多个后置摄像头(广角、长焦等)。
- 适配功能对齐差异:闪光灯、自动对焦等在不同硬件上行为不同;例如 CameraX 同时处理物理后置闪光与屏幕前置闪光,实现闪光灯功能时两者都要顾及。
- 异步生命周期:在 stop 或 pause 之前先检查 `isRecording` 状态;用 `VideoRecordEvent.Start` 驱动 UI 状态更新,而不要只依赖初始调用。
- 线程安全:相机回调常运行在后台 executor 上,UI 更新必须切回主线程。
- 权限处理:检查 `CAMERA` 权限;在 `VideoCapture` 中启用音频时,额外检查 `RECORD_AUDIO` 权限。
适用边界 · 注意事项
- 不适用于非 Android 平台的相机开发(iOS、Web、桌面原生等)。
- 当项目不使用 CameraX 而坚持纯 Camera2/Camera1 深度定制时,其中的高层抽象与迁移建议不直接适用。
- 在对性能有绝对要求、必须手写 OpenGL 管线的场景,『优先用 Media3Effect/SurfaceProcessor』的建议应让位。