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



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

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

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

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

在进行进一步测试(打开主要活动并在连接设备之前远离它)时,我发现出于某种原因,运行的服务可能有两个实例。

这里发生了什么,我如何可靠地检测到USB设备已断开连接?

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

  • 如上所述,该服务不仅在USB设备连接时就可以启动,还可以在其他事件(例如已连接到AC适配器的设备或打开的主要活动)上开始。在这些情况下
  • 结果,当启用自动连接时,打开主要活动将始终启动第一个服务实例。如果USB设备在之后连接,那么我们显然可能会运行两个服务实例。我怀疑断开的广播可能会被错误的实例所吸收。
  • 如果我禁用AutoConnect,则该服务确实会接收断开事件,但会忽略它,因为设备不相同。然而,日志输出显示两个设备的设备路径相同。进一步的分析表明,我只是使用!=比较了两个UsbDevice实例,该实例未能捕获两个不同的类实例,参考了同一设备。

所以我们需要做两件事:

  • 使用 UsbDevice#equals()而不是相等性操作员进行比较。
  • 防止多个服务实例运行。确保在找不到设备并将意图交付到现有实例而不是启动新的实例时,请确保服务退出。

最新更新