Android 通知单击保持堆栈并在需要时将应用程序置于最前面。如果特定活动在顶部,则传递数据

Posted

技术标签:

【中文标题】Android 通知单击保持堆栈并在需要时将应用程序置于最前面。如果特定活动在顶部,则传递数据【英文标题】:Android Notification click keep stack and bring app to front if need. Pass data if specific activity is on top 【发布时间】:2020-10-09 14:17:14 【问题描述】:

如何单击通知,在需要时将我的应用程序置于前台,并保持堆栈不变(即使应用程序进入后台)?

我有一个NotificationClickActivity,当用户单击通知时会启动它。

点击通知时,我有两种可能的情况:

    用户已从应用程序中注销 用户已登录。

在第一个场景中,NotificationClickActivity 启动登录过程并接收结果。如果OK,我启动MainActivity。任务被清除,所以MainActivity 是我在任务中的唯一活动。在这种情况下我没有问题。

在第二种情况下NotificationClickActivity 这样做:

finish()  
startActivity(MainActivity.createIntent(this).setFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP).putExtra("notification", notification))

使用上面的代码,如果应用程序已经在运行(MainActivity 是根和***活动)并且在后台或前台,我没有问题。 MainActivity onNewIntent 被调用,我可以对通知做任何事情。在这种情况下,我将通知发送到存储库。

我面临的问题是当我在MainActivity 之上进行活动时。想象一下下面的堆栈:

MainActivity -> ActivityOne -> ActivityTwo -> ActivityN

如果我单击通知,堆栈变为:

MainActivity -> ActivityOne -> ActivityTwo -> ActivityN -> MainActivity

我希望堆栈保持MainActivity -> ActivityOne -> ActivityTwo -> ActivityN,但仍将通知传递给MainActivity,以便可以将其分派到存储库。

知道如何实现这一目标吗?

我一直在使用意图标志,但没有成功。 当然,我没有任何可见的动画或其他任何东西,这样用户就不会意识到发生了什么。

【问题讨论】:

【参考方案1】:

认为您正在寻找FLAG_ACTIVITY_REORDER_TO_FRONT

.setFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP || FLAG_ACTIVITY_REORDER_TO_FRONT)

如果 Activity 已经在运行,这会将其带到栈顶。

考虑一个由四个活动组成的任务:A、B、C、D。如果 D 调用 startActivity() 的 Intent 解析为活动 B 的组件,则 B 将被带到历史堆栈的前面,结果顺序为:A、C、D、B。

在上面的示例中,如果您想从 A,B,C,D 转到 A,B,C,D,B,则需要确保您的 Activity 支持多个实例。

建议 FLAG_ACTIVITY_SINGLE_TOP 改为在 android 清单中为活动指定。然后在您的onNewIntent 中检查用户是否已登录。如果用户未登录,则应使用startActivityForResult 启动登录过程并使用onActivityResult 处理登录结果。

这假设您的登录可以通过 Intent 启动,该 Intent 调用 setResult 并提供足够的信息供调用者确定登录是否成功。

至于动画,我认为您将不得不使用片段并禁用动画,或者禁用 Activity 的动画,并且仅在需要时进行自定义转换。这甚至可能不适用于 Activity,因为无论如何,操作系统/OEM 定义的转换可能只会发生在 Activity 中,因此您很可能必须确保应用程序的其余部分在同一个 Activity 中并使用片段进行导航。


【讨论】:

谢谢,但我不想重新排序到前面。此外,当我的用户注销时,我没有任何问题。我只有当他登录并且堆栈是 A、B、C、D 时才有。在这种情况下,单击通知我想将堆栈保持为 A、B、C、D 但是: 1 - 将信息传递给 A和 2 - 如果应用程序在后台,则将其置于前台。另一种可能性是检查最重要的活动是什么。 对。简短的回答是否定的。将信息传递给活动的唯一方法是将其从暂停状态中恢复,这意味着它开始并来到前面。我相信你想要的是更新一些状态,A 可以在下一次“恢复”时刷新。为此,您可以使用没有任何 UI 的单独活动来处理意图和完成。根据将当前活动放在前面,您可能可以使您的意图更通用。设置类别和包名称,但不指定活动。认为这就是单击启动器图标时发生的情况。这可能行得通。【参考方案2】:

使用这种方法是不可能的。如果当前任务包含MainActivity 以及除此之外的其他活动,则无法使用startActivity 或启动Activity

如果您需要向MainActivity 获取信息,那么您需要使用另一种机制来执行此操作:

发送广播 Intent 并让 MainActivity 收听广播 使用事件总线实现 使用“全局变量”在 2 个活动之间传递此信息

【讨论】:

以上是关于Android 通知单击保持堆栈并在需要时将应用程序置于最前面。如果特定活动在顶部,则传递数据的主要内容,如果未能解决你的问题,请参考以下文章

Android - 点击时 Firebase 通知会打开一个 Activity

单击按钮向 android 应用程序的用户发送通知

Android 应用程序未在 Com.onesignal 通知中启动单击

当一个活动直接从一个通知启动时,你如何构建一个 Android 后台堆栈?

单击通知时如何保留当前的返回堆栈(或任务)?

推入导航堆栈时隐藏 TabBar 并在弹出导航堆栈时将其返回