如果应用程序已经 运行,则如何在连接 USB 附件时接收 Intent

How to receive Intent when USB Accessory is attached if application is already running

我能够阅读 here 关于如何在连接 USB 配件时启动我的应用程序,并且一切正常:我的清单中内置了一个 IntentFilter,它将启动适当的 activity 每次附上指定的配件。这是它的样子:

<activity
        android:name=".MainActivity"
        android:label="@string/app_name"
        android:exported="true">
        <intent-filter>
            <action android:name="android.hardware.usb.action.USB_ACCESSORY_ATTACHED" />
        </intent-filter>

        <meta-data
            android:name="android.hardware.usb.action.USB_ACCESSORY_ATTACHED"
            android:resource="@xml/accessory_filter" />
</activity>

但是,如果我的 Activity 在连接附件时已经 运行,我就会遇到问题。在 MainActivity 中,我在两个地方寻找 USB_ACCESSORY_ATTACHED Intent:onCreate 和 onNewIntent,如下所示:

protected void onCreate(Bundle savedInstanceState) {
    //Check for some other actions first
    if (UsbManager.ACTION_USB_ACCESSORY_ATTACHED.equals(intent.getAction()))
        usbAttached(intent);

}
protected void onNewIntent(Intent intent) {
    if (UsbManager.ACTION_USB_ACCESSORY_ATTACHED.equals(intent.getAction()))
        usbAttached(intent);
}

但是,如果 MainActivity 已经 运行,则在插入配件时既不会调用 onCreate 也不会调用 onNewIntent。在那种情况下,我需要在插入配件之前关闭我的应用程序,这对用户来说会很麻烦。如果我的 activity 已经是 运行,从我的 USB 配件接收 Intent 的适当方式是什么?我是否需要在 activity 本身内实现一个单独的侦听器?

编写 BroadcastReceiver 并通过 Context.registerReceiver(...) 在您的 activity 生命周期方法中注册它。不要忘记在相应的拆卸生命周期方法中注销它。

如果您查看 onNewIntent() 的文档,它会显示:

protected void onNewIntent (Intent intent)

Added in API level 1
This is called for activities that set launchMode to "singleTop" in their package, or if a client used the FLAG_ACTIVITY_SINGLE_TOP flag when calling startActivity(Intent). In either case, when the activity is re-launched while at the top of the activity stack instead of a new instance of the activity being started, onNewIntent() will be called on the existing instance with the Intent that was used to re-launch it.
...

因此您需要在清单中将 ActivitylaunchMode 设置为 singleTop,否则您将不会收到对 onNewIntent() 的呼叫。结果应如下所示:

<activity
        android:name=".MainActivity"
        android:label="@string/app_name"
        android:launchMode="singleTop"
        android:exported="true">
           ... 
</activity>

如果你仔细想想,这种行为实际上很有意义。下次在此处询问之前先查看文档。如果您不知道,请不要假设这些东西是如何工作的。