Android的NFC前台调度系统有bug吗?

vRa*_*lev 5 android foreground nfc dispatch android-activity

我对前台调度行为有一个恼人的问题。有时onNewIntent()它会完全重新创建 Activity而不是调用,这会破坏应用程序的工作流程。

我的具体情况:Activity A是MainActivity,使用前台调度。一切正常。但是,在我从浏览器启动的活动 B(VIEW 操作)中,前台调度在某些情况下不再起作用。

工作流程:

  • 我启动 MainActivity,切换到浏览器(不关闭 MainActivity),启动 Activity B 并连接我的 NFC 设备 --> 它创建了一个新的 Activity B。

  • 我启动 MainActivity 并再次关闭它。之后我切换
    到浏览器,启动活动 B 并连接我的 NFC 设备 --> 一切正常onNewIntent()

代码是正确的,例如,如果我在第一个场景中两次连接 NFC 设备,它会在第二次正常工作,但在第一次不正常。在 MainActivity 和活动 BI 中明确调用活动的 onPause() 方法中的 disableForegroundDispatch() 方法。

我的具体问题有解决方案吗?对我来说,这听起来像是一个错误。

编辑:

public void resume(Activity targetActivity) {
    if (nfc != null && nfc.isEnabled()) {
        // nfc is the default NFC adapter and never null on my devices

        Intent intent = new Intent(targetActivity, targetActivity.getClass()).addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP);
        PendingIntent pendingIntent = PendingIntent.getActivity(targetActivity, 0, intent, 0);
        nfc.enableForegroundDispatch(targetActivity, pendingIntent, null, new String[][] { new String[] { IsoDep.class.getName() } });
    }
}

public void pause(Activity targetActivity) {
    if (nfc != null && nfc.isEnabled()) {
        nfc.disableForegroundDispatch(targetActivity);
    }
}
Run Code Online (Sandbox Code Playgroud)

这些方法在每个活动的相应方法中被调用。谢谢您的帮助!

解决方案:经过很长时间的研究,我终于找到了问题所在。Logcat 打印:

  • 从非活动上下文调用的 startActivity;强制 Intent.FLAG_ACTIVITY_NEW_TASK 用于:意图

我在 Stackoverflow 上发现了其他问题,人们对 NotificationManager 有同样的问题,但所有的提示都没有帮助我。将标志 singleTask 添加到我的活动 B 对我有用,但老实说我不理解它,因为上下文始终是一个活动。

我从 MainActivity 中删除了所有代码,第一个场景仍然不起作用。我从清单中删除了 MainActivity,之后一切都很好。也许这是一个问题,一个应用程序实例正在运行,而 Activity B 是从浏览器启动的?我不知道。

无论如何,感谢NFC家伙的帮助!

NFC*_*guy 2

您传递IntentFilter[]给的enableForegroundDispatch是空的。因此,由于清单文件中的 IntentFilter,您的 NFC 意图可能会到达您的 Activity。这解释了您观察到的行为,因为 NFC 意图在以这种方式传递时总是创建一个新实例。

将类似的内容添加到代码中以启用前台调度:

IntentFilter[] iFilters = new IntentFilter[2];
iFilters[0] = new IntentFilter();
iFilters[0].addAction("android.nfc.action.TECH_DISCOVERED");
iFilters[1] = new IntentFilter();
iFilters[1].addAction("android.nfc.action.TAG_DISCOVERED");
iFilters[1].addCategory(Intent.CATEGORY_DEFAULT);
Run Code Online (Sandbox Code Playgroud)

并将其作为参数传递给enableForegroundDispatch.

更新:我最近了解了有关这个具体问题的更多信息。这是由 Android 确定应在哪个任务中启动新 Activity 的方式引起的。我不知道也不了解其工作原理的具体细节,但效果是:

  1. 当 Activity B 从浏览器启动时,它会在浏览器的任务中创建
  2. 当NFC意图到达时,系统确定要在Activity A的任务中创建一个新的Activity B

因为 2.,SINGLE_TOP 不会被忽略:A 任务的顶部只有一个 Activity B 实例。当 Activity A 关闭时,它的任务就消失了,因此 Activity B 将始终在浏览器的任务中创建,正如您所观察到的。

在这种情况下,您可能会觉得这是一个 Android 错误(我确实如此,我认为),但这种如何在任务中创建活动的行为对于 Android 来说是如此基础,以至于许多应用程序都依赖它。因此,这种情况不太可能改变。

可能的解决方法:使用launchMode“singleTask”(或“singleInstance”)声明 Activity B。然后,当 B 启动时,将创建一个新的(第三个)任务。