在“设置 → 相机设置”中切换人脸识别摄像头后,设备能够成功打开,UVC 原生层也持续收到 640x480 视频帧,但预览区域偶发持续黑屏。
原实现使用 UVCCamera.setPreviewTexture(SurfaceTexture) 绑定预览。该 UVC 库会在方法内部临时创建 Surface,业务层无法持有和释放这个对象。
切换、暂停和页面销毁时,原实现调用 setPreviewTexture(null) 尝试解绑,但库内部会执行 new Surface(null),直接抛出 IllegalArgumentException: surfaceTexture must not be null。因此旧预览输出面并未按预期解绑和释放。重复切换后,旧输出面可能继续占用同一个 BufferQueue,最终形成“相机有帧但 TextureView 黑屏”的状态。
SurfaceTexture 只复用一个 Surface。SurfaceTexture,下次启动也会创建全新的 Surface。Surface,并调用 setPreviewDisplay(Surface)。setPreviewDisplay(null) 从 UVC 原生层解绑,再调用 Surface.release()。setPreviewTexture(null) 清理调用,避免无效解绑和异常。采用测试先行:
完整验证:
./gradlew :app:testDebugUnitTest :app:assembleDebug --rerun-tasks:成功,94 个任务重新执行。git diff --check:通过。USB2.0_CAM1 (11391/19040) 与 USB 2.0 Camera (3141/25440) 之间连续往返切换 6 次:
surfaceTexture must not be null、Surface 清理异常、Java 崩溃或 UVC 原生崩溃。本次仅修正公共 UvcCameraController 的预览 Surface 生命周期,并增加对应单元测试。设置页人脸相机预览直接受益;复用该控制器的 UVC 测试页面同样获得规范的 Surface 清理行为。未修改菜品识别算法、人脸识别算法、支付流程、接口协议或 Git 历史。