检测USB OTG设备何时断开连接

时间:2019-03-06 00:16:46

标签: android usb-otg

我有一个与USB OTG设备交互的应用程序:

  • 连接USB设备后,将启动帮助程序活动以显示Android确认对话框。这是通过清单中的IntentFilter完成的。
  • helper活动启动服务是通过向其发送特定于应用程序的意图来启动的。
  • 服务的onCreate()方法将填充IntentFilter,并添加服务在运行时应做出的反应,包括UsbManager.ACTION_USB_DEVICE_DETACHED。添加额外的调试输出会告诉我该方法在预期的时间运行,即在我注册接收器时填充了IntentFilter
  • 服务的onStartCommand()方法调用一个内部方法,该方法为意图过滤器注册BroadcastReceiver(如果该服务是用启动意图启动的,并且具有必要的权限,否则该服务将终止)。
  • 当接收方收到UsbManager.ACTION_USB_DEVICE_DETACHED并且报告的设备是当前连接的设备时,它将停止服务。
  • 还有一个主要活动,不涉及处理USB设备。
  • 该服务也由于其他原因而被调用,特别是在连接充电器时。在这种情况下,服务将寻找蓝牙设备(如果已连接USB设备(由服务实例的成员为非空指示),则将其跳过并退出服务。

现在,如果我插入USB设备,则会得到确认,并且服务会启动,并且在拔出设备时,服务会再次停止。到目前为止,一切都很好。

但是,在某些情况下,即使拔下设备,服务仍保持运行。我注意到在连接设备时打开主活动时总是会发生这种情况。日志显示该服务从未收到UsbManager.ACTION_USB_DEVICE_DETACHED广播

在做进一步测试(在连接设备之前打开主要活动并导航至远离活动)时,我发现有证据表明可能有两个服务正在运行的实例

这是怎么回事,如何可靠地检测到USB设备已断开连接?

1 个答案:

答案 0 :(得分:0)

此行为似乎是由两个因素引起的:

  • 如上所述,该服务不仅在连接USB设备时启动,而且在其他事件(例如,该设备连接到AC适配器或正在打开主要活动)时启动。在这种情况下,它将查找蓝牙设备(“自动连接”),如果找不到蓝牙设备或已经连接了USB设备,则退出。
  • 因此,启用自动连接后,打开主活动将始终启动第一个服务实例。如果USB设备在之后连接,则显然我们可能正在运行两个服务实例。我怀疑断开广播可能会被错误的实例接收。
  • 如果禁用自动连接,则该服务确实会收到断开连接事件,但会忽略该事件,因为设备被认为不相等。但是,日志输出显示两个设备的设备路径相同。进一步的分析表明,我只是使用!=来比较两个UsbDevice实例,但无法捕获引用同一设备的两个不同的类实例。

所以我们需要做两件事:

  • 使用UsbDevice#equals()而不是相等运算符进行比较。
  • 防止该服务的多个实例运行。确保在找不到任何设备时退出服务,并且将Intent传递到现有实例,而不是启动新实例。