uni-app 无法直接监听 USB 连接状态,必须通过原生 Android 插件实现:注册 BroadcastReceiver 监听 ACTION_USB_DEVICE_ATTACHED/DETACHED 广播,声明硬件权限与 intent-filter,动态注册广播,JS 层通过 uni.$on 订阅事件,并确保解锁亮屏、USB 调试开启、设备支持 Host 模式及插件正确签名。

uni-app 无法直接监听 USB 连接状态
uni-app 的 JavaScript 层(包括 uni.onNetworkStatusChange、plus.device 等 API)**不提供监听 USB 插拔事件的能力**。这不是配置问题,而是平台限制:App SDK 没有暴露该系统级广播的 JS 接口。试图用 uni.getSystemInfo 或轮询 plus.io 都无效。
Android 原生层必须用 BroadcastReceiver 监听 ACTION_USB_DEVICE_ATTACHED
真机上要响应 USB 插入/拔出,只能靠原生插件。核心是注册系统广播:ACTION_USB_DEVICE_ATTACHED 和 ACTION_USB_DEVICE_DETACHED(注意不是 ACTION_POWER_CONNECTED,后者只管充电)。
关键点:
- 需在
AndroidManifest.xml中声明<uses-feature android:name="android.hardware.usb.host" />和对应<intent-filter> - 权限声明
android.permission.USB_PERMISSION是必须的,且首次连接需用户手动授权(弹窗“允许此应用访问 USB 设备”) - 不能在 Activity 生命周期外长期持有 BroadcastReceiver,建议在自定义
UniPlugin的onCreate中动态注册,并在onDestroy解注册 - 插件收到广播后,通过
callbackContext.success()或sendPluginResult()主动通知 JS 层
JS 层如何安全接收原生插件的 USB 状态通知
原生插件发来的消息,JS 侧不能依赖全局变量或随意挂载事件。推荐做法:
- 在
App.vue的onLaunch中调用插件初始化方法(如usbMonitor.init()),确保插件已就绪 - 用
uni.$on('usb-connected', handler)订阅事件,避免多次绑定;退出时用uni.$off('usb-connected')清理 - 不要在页面
onLoad里重复 init —— USB 状态是全局设备事件,与页面无关 - 插件返回的 device info(如 vendorId、productId)应作为参数传给 JS,便于区分扫码枪、读卡器等不同外设
常见失败原因和绕不过去的坑
即使代码写对,也大概率卡在以下环节:
- 华为/小米手机默认关闭「USB 调试」下的「USB 安装」和「USB 调试(安全设置)」,这两个开关必须同时打开,否则
ACTION_USB_DEVICE_ATTACHED广播根本不会发出 - USB 设备插入时,手机必须处于解锁亮屏状态,锁屏下系统会丢弃大部分 USB 广播
- 部分 OTG 转接头或 USB 设备不支持 Android Host 模式(比如仅支持 Device 模式),此时手机根本识别不到设备
- 插件未签名或签名证书与基座不一致 → 安装失败或运行时报错
java.lang.SecurityException: Permission Denial
真正能稳定工作的方案,永远是“原生插件 + 显式用户授权 + 解锁亮屏 + 正确签名”,缺一不可。别指望纯 JS 实现。


















