You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Android平板如何正确检测QR扫描设备的连接与断开?

解决QR扫描设备(如BC-NL3000UⅡ)的USB插拔检测问题

你的代码能检测普通USB设备,但对这类QR扫描设备失效,核心原因是多数扫码器会被系统识别为HID键盘类设备,这类设备的插拔事件不会触发标准的UsbManager.ACTION_USB_DEVICE_ATTACHED/DETACHED广播,USB_STATE广播也无法精准捕捉。以下是针对性的解决方法:

方法1:监听InputDevice的插拔事件

因为扫码器模拟键盘输入,属于输入设备范畴,可通过监听InputDevice相关广播来检测:

步骤1:注册广播接收器

注册监听输入设备的添加/移除广播:

val inputDeviceReceiver = object : BroadcastReceiver() {
    override fun onReceive(context: Context?, intent: Intent?) {
        intent ?: return
        when (intent.action) {
            "android.hardware.input.action.INPUT_DEVICE_ADDED" -> {
                val deviceId = intent.getIntExtra("android.hardware.input.extra.DEVICE_ID", -1)
                if (deviceId != -1) {
                    val device = InputDevice.getDevice(deviceId)
                    if (isQrScanner(device)) {
                        sendEventToFlutter("onUsbConnected")
                    }
                }
            }
            "android.hardware.input.action.INPUT_DEVICE_REMOVED" -> {
                val deviceId = intent.getIntExtra("android.hardware.input.extra.DEVICE_ID", -1)
                if (isTargetScannerId(deviceId)) {
                    sendEventToFlutter("onUsbDisconnected")
                }
            }
        }
    }
}

// 在Activity/Fragment的onCreate中注册,onDestroy中注销
val filter = IntentFilter().apply {
    addAction("android.hardware.input.action.INPUT_DEVICE_ADDED")
    addAction("android.hardware.input.action.INPUT_DEVICE_REMOVED")
}
context.registerReceiver(inputDeviceReceiver, filter)

步骤2:筛选目标扫码设备

实现设备匹配逻辑,通过名称或VID/PID定位目标扫码器:

private fun isQrScanner(device: InputDevice): Boolean {
    // 可通过adb命令`adb shell dumpsys input`获取设备的名称、VID/PID
    return device.name.contains("BC-NL3000UⅡ") 
           || (device.vendorId == 0xXXXX && device.productId == 0xXXXX)
}

// 维护已连接的目标设备ID,用于断开时匹配
private var connectedScannerId = -1
private fun isTargetScannerId(deviceId: Int): Boolean {
    return deviceId == connectedScannerId
}

方法2:主动枚举USB设备(兜底方案)

如果广播监听不稳定,可定时枚举USB设备,对比列表变化判断插拔:

private var lastDeviceList: List<UsbDevice> = emptyList()

// 每2秒执行一次设备枚举
val timer = Timer().scheduleAtFixedRate(object : TimerTask() {
    override fun run() {
        val usbManager = context.getSystemService(Context.USB_SERVICE) as UsbManager
        val currentDevices = usbManager.deviceList.values.toList()
        
        val addedDevices = currentDevices.filter { !lastDeviceList.contains(it) }
        val removedDevices = lastDeviceList.filter { !currentDevices.contains(it) }
        
        addedDevices.forEach { device ->
            if (isQrScannerUsb(device)) {
                sendEventToFlutter("onUsbConnected")
            }
        }
        
        removedDevices.forEach { device ->
            if (isQrScannerUsb(device)) {
                sendEventToFlutter("onUsbDisconnected")
            }
        }
        
        lastDeviceList = currentDevices
    }
}, 0, 2000)

private fun isQrScannerUsb(device: UsbDevice): Boolean {
    return device.vendorId == 0xXXXX && device.productId == 0xXXXX
}

补充注意事项

  • 确保APP拥有android.permission.USB_PERMISSION权限,可在Manifest中声明:
    <uses-permission android:name="android.permission.USB_PERMISSION" />
    
  • 部分扫码器支持切换工作模式(如从HID模式切换到USB串口模式),切换后可通过标准USB广播检测,同时需要串口通信库配合。

内容的提问来源于stack exchange,提问作者Tuan Pham Cong

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.14 14:05:06