uni-app无法直接调用usb摄像头,必须通过android原生插件(如serenegiant/usb-camera-lib)实现:需声明usb权限、注册广播监听设备接入、初始化uvc协议栈,并通过jsbridge桥接控制方法,拍照结果须存为本地文件路径。

uni-app 本身不支持直接调用 USB 摄像头,必须通过 Android 原生模块扩展实现。 它连 MediaDevices.getUserMedia() 都不透出给 H5 层(尤其在 App 端),更不会识别 USB 设备枚举。所谓“调用”,本质是写 Java/Kotlin 插件 + 在 uni-app 里桥接调用。
为什么 uni.chooseImage 和 组件完全无效
这两个 API 只面向设备内置摄像头(CameraManager 或 Camera2 系统服务),底层走的是 Android 的 Camera API 路径;而 USB 摄像头属于 USB 设备,需通过 UsbManager + USBMonitor + UVC 协议栈通信,两者驱动层、权限模型、生命周期完全不同。
-
uni.chooseImage({ sourceType: ['camera'] })会静默失败或直接打开后置摄像头,对 USB 设备无感知 -
<camera></camera>组件在 App 端渲染时强制绑定系统默认 camera ID,无法传入自定义 surface 或 byte buffer 流 - H5 环境下
getUserMedia()在 Android WebView 中默认禁用 USB 设备枚举(Chrome for Android 不开放该能力)
Android 原生插件必须做的三件事
你得在 android/app/src/main/java/... 下新增一个模块,不能只靠 npm 插件自动集成——几乎所有公开的 cordova/uni-app USB 插件都缺少关键适配,真机上会卡在权限或设备未就绪。
- 在
AndroidManifest.xml中声明 USB 权限:<uses-feature android:name="android.hardware.usb.host"></uses-feature>和<uses-permission android:name="android.permission.USB_PERMISSION"></uses-permission> - 注册
<intent-filter></intent-filter>拦截 USB 设备接入广播,否则onAttach不触发 - 使用
serenegiant/usb-camera-lib(v2.3.1+)而非旧版,它封装了 UVC 初始化、YUV→RGB 转换、SurfaceTexture 绑定逻辑;手动调用USBMonitor.start()后必须等onConnect回调完成才能 openDevice
uni-app 如何安全桥接到原生 USB 视频流
不能直接把 byte[] 或 Surface 传给 JS 层——性能崩、内存泄漏、跨线程 crash 高发。正确做法是:原生侧将帧数据渲染到 SurfaceView 或 TextureView,再通过 plus.android.importClass 暴露控制方法,JS 层只发指令、收状态。
- 暴露方法示例:
startUsbCamera()、stopUsbCamera()、takeUsbPhoto()(内部调用 lib 的captureFrame()) - 拍照结果必须存为本地文件路径(如
/storage/emulated/0/DCIM/usb_202609051234.jpg),再通过uni.uploadFile()上传,不要尝试转 base64 - 务必检查
UsbDevice.getInterfaceCount() > 0和UsbInterface.getEndpointCount() > 1,部分廉价 USB 摄像头只提供单 endpoint,无法稳定采集
真正难的不是调通第一帧,而是处理 USB 设备热拔插、多摄像头冲突、低照度下 YUV 噪点导致的 RGB 渲染错位、以及 Android 12+ 对后台 USB 权限的限制——这些细节没写进任何插件文档,只能看 logcat -s UVCCamera 日志逐行对齐。











