如果应用程序已经 运行,则如何在连接 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.
...
因此您需要在清单中将 Activity
的 launchMode
设置为 singleTop
,否则您将不会收到对 onNewIntent()
的呼叫。结果应如下所示:
<activity
android:name=".MainActivity"
android:label="@string/app_name"
android:launchMode="singleTop"
android:exported="true">
...
</activity>
如果你仔细想想,这种行为实际上很有意义。下次在此处询问之前先查看文档。如果您不知道,请不要假设这些东西是如何工作的。
我能够阅读 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.
...
因此您需要在清单中将 Activity
的 launchMode
设置为 singleTop
,否则您将不会收到对 onNewIntent()
的呼叫。结果应如下所示:
<activity
android:name=".MainActivity"
android:label="@string/app_name"
android:launchMode="singleTop"
android:exported="true">
...
</activity>
如果你仔细想想,这种行为实际上很有意义。下次在此处询问之前先查看文档。如果您不知道,请不要假设这些东西是如何工作的。