意图 - 如果活动正在运行,请将其放在前面,否则启动一个新活动(来自通知)
Posted
技术标签:
【中文标题】意图 - 如果活动正在运行,请将其放在前面,否则启动一个新活动(来自通知)【英文标题】:Intent - if activity is running, bring it to front, else start a new one (from notification) 【发布时间】:2013-10-03 01:37:52 【问题描述】:我的应用有通知,显然 - 没有任何标志,每次都会启动一个新的活动,所以我得到多个相同的活动在彼此之上运行,这是错误的。
我想要它做的是将通知待处理意图中指定的活动放在前面,如果它已经在运行,否则启动它。
到目前为止,我拥有的该通知的意图/待定意图是
private static PendingIntent prepareIntent(Context context)
Intent intent = new Intent(context, MainActivity.class);
intent.setFlags(Intent.FLAG_ACTIVITY_REORDER_TO_FRONT);
return PendingIntent.getActivity(context, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT);
奇怪的是,它有时有效,有时无效……我觉得我已经尝试过每一种标志组合。
【问题讨论】:
【参考方案1】:我认为最好的简单方式是正常启动活动,但在清单中使用singleInstance
属性设置该活动。有了这个,您实际上可以解决您现在遇到的两个问题,方法是始终将活动置于最前面,并让操作系统在不存在活动时自动创建一个新活动,或者将当前存在的活动置于最前面(感谢singleInstance
属性)。
这是将活动声明为单个实例的方式:
<activity
android:name=".YourActivity"
android:launchMode="singleInstance"/>
另外,为了避免在通过 singleInstance 启动时出现断断续续的动画,您可以使用“singleTask”来代替,两者非常相似,但这里根据 Google 的文档解释了不同之处:
<activity
android:name=".YourActivity"
android:launchMode="singleTask"/>
singleInstance 与“singleTask”相同,只是系统 不会在持有该任务的任务中启动任何其他活动 实例。该活动始终是其唯一且唯一的成员 任务。
希望这会有所帮助。
问候!
【讨论】:
它似乎有效,但现在我从 singleIntent MainActivity 启动的所有其他新活动,播放这个奇怪的弧形动画而不是常规的淡入淡出和缩放 如果我每次都启动一个新的活动,但清除它所有其他正在运行的实例,这可能吗? 好吧,我认为您提到的动画与“singleInstance”属性没有任何关系,它所做的只是重用现有实例,也许您正在谈论的动画是一个完全不同的问题... 嗯,我现在正在测试它,它确实如此。如果我删除所有意图标志并在清单中设置 launchMode="singleInstance",那么奇怪的动画就在那里,如果我删除它,它就会恢复正常 是的,根据android文档,“init”动画似乎不再像往常一样存在,因为活动没有被初始化,只是被重用......【参考方案2】:你可以用这个:
<activity
android:name=".YourActivity"
android:launchMode="singleTask"/>
这将类似于"singleInstance"
,但它不会有那种奇怪的动画。
【讨论】:
+1,您应该是公认的答案。区别在这里:developer.android.com/guide/topics/manifest/… 澄清一下,如果您在应用程序中有多个活动并且这是父活动,请使用 singleTask,如果您只有一个活动,请使用 singleInstance。 如果像我这样的人在最终访问此站点之前尝试了多种解决方案组合:请确保摆脱您尝试过的其他更改,并确保对正确的活动进行此更改。我花了很长时间才发现如果我没有尝试其他解决方案(例如覆盖onNewIntent
和设置标志),这个解决方案会起作用
我有一张 Messenger、Activity 对的地图。如果我收到消息,我想显示 Activity 实例。有没有办法做到这一点。例如:HashMap.get(Messenger).bringActivityToFront();我的意思是,活动仍在进行中。如果我打开最近的任务并单击它,它将 onResume();我不能以编程方式 onResume()。
@JaveneCPPMcGowan 这似乎是一个完全不同的问题,我建议您将其发布为自己的问题,不幸的是我真的不知道答案。【参考方案3】:
既然你说你想开始你的活动,如果它还没有开始,也许你不介意重新开始它。我还针对意图测试了大量建议和标志组合,这将始终将您需要的活动带到最前面,尽管它不会保留以前与之关联的任何状态。
intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK|Intent.FLAG_ACTIVITY_NEW_TASK);
仅限 API11+。
【讨论】:
【参考方案4】:我认为您需要的是singleTop
Activity
,而不是singleTask
或singleInstance
。
<activity android:name=".MyActivity"
android:launchMode="singleTop"
...the rest... >
the documentation says 完全符合您的需求:
[...] 还可以创建一个“
singleTop
”活动的新实例来处理 一个新的意图。但是,如果目标任务已经存在 位于其堆栈顶部的活动实例,该实例将 接收新意图(在onNewIntent()
呼叫中);一个新实例是 未创建。在其他情况下——例如,如果现有 “singleTop
”活动的实例在目标任务中,但不在 堆栈的顶部,或者如果它在堆栈的顶部,但不在 目标任务——将创建一个新实例并将其推送到堆栈上。
除此之外(不是双关语),我的需求与您完全相同。我测试了所有launchMode
标志以了解它们在实践中的实际行为,结果singleTop
实际上是最好的:没有奇怪的动画,应用程序在最近的应用程序列表中显示一次(不像singleInstance
显示它两次,因为它不允许任何其他 Activity
成为其任务的一部分),并且无论目标 Activity
是否已经存在,都应采取适当的行为。
【讨论】:
周五晚上工作到晚上 10 点,这就是我想要的……悲伤的开发人员生活。 节省了我很多时间!谢谢!【参考方案5】:我试过了,即使 IDE 抱怨代码,它也能正常工作
Intent notificationIntent = new Intent(THIS_CONTEXT, MainActivity.class);
notificationIntent.setFlags(Intent.FLAG_ACTIVITY_REORDER_TO_FRONT);
PendingIntent intent = PendingIntent.getActivity(THIS_CONTEXT, 0, notificationIntent, Intent.FLAG_ACTIVITY_REORDER_TO_FRONT);
NotificationCompat.Builder mBuilder = new NotificationCompat.Builder(THIS_CONTEXT)
.setSmallIcon(R.drawable.cast_ic_notification_0)
.setContentTitle("Title")
.setContentText("Content")
.setContentIntent(intent)
.setPriority(PRIORITY_HIGH) //private static final PRIORITY_HIGH = 5;
.setAutoCancel(true)
/*.setDefaults(Notification.DEFAULT_SOUND | Notification.DEFAULT_VIBRATE | Notification.DEFAULT_LIGHTS)*/;
NotificationManager mNotificationManager = (NotificationManager) THIS_CONTEXT.getSystemService(Context.NOTIFICATION_SERVICE);
mNotificationManager.notify(0, mBuilder.build());
【讨论】:
Intent.FLAG_ACTIVITY_REORDER_TO_FRONT
不是PendingINtent.getActivity
的有效标志
@rds 你能链接源吗?
@LouisCAD 对不起,我无法再访问源代码了
@rds 我不是要源代码,而是要你读到Intent.FLAG_ACTIVITY_REORDER_TO_FRONT
在用作PendingIntent
时不是有效标志的链接。或者,也许您的意思是传递给getActivity
方法是无效的,但可以用作Intent
标志,然后用作PendingIntent
?【参考方案6】:
我知道它已经过时了,但以上内容都不适合我的应用程序。
在不更改清单和其他配置的情况下,这里是让您的应用回到前面的代码 - 或者在关闭时打开它
Intent notificationIntent = context.getPackageManager().getLaunchIntentForPackage(context.getPackageName());
notificationIntent.setPackage(null); // The golden row !!!
notificationIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED);
【讨论】:
这才是真正的答案! 不,它不起作用 - 它会在当前活动之上添加一个新活动。 @Tobliug 我想如果您尝试删除标志FLAG_ACTIVITY_NEW_TASK
会为您工作?【参考方案7】:
这是旧线程,但对于所有仍在寻求答案的人,这是我的解决方案。它纯粹是代码,没有清单设置:
private static PendingIntent prepareIntent(Context context)
Intent intent = new Intent(context, MainActivity.class);
intent.setFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP | Intent.FLAG_ACTIVITY_CLEAR_TOP);
return PendingIntent.getActivity(context, NON_ZERO_REQUEST_CODE, intent,
PendingIntent.FLAG_UPDATE_CURRENT);
这里 FLAG_ACTIVITY_SINGLE_TOP 打开现有活动,如果它位于任务堆栈的顶部。如果它不在顶部,而是在堆栈内部,FLAG_ACTIVITY_CLEAR_TOP 将删除目标活动顶部的所有活动并显示它。如果 Activity 不在任务堆栈中,则将创建新的。需要提到的一个至关重要的点 - PendingIntent.getActivity() 的第二个参数,即 requestCode 应该具有非零值(我什至在我的 sn-p 中将其称为 NON_ZERO_REQUEST_CODE),否则这些意图标志将不起作用。我不知道为什么会这样。标志 FLAG_ACTIVITY_SINGLE_TOP 可与 android:launchMode="singleTop" 互换 在清单中的活动标签中。
【讨论】:
用这些标志打了几个小时,想知道为什么改变我的意图标志并没有改变任何东西。非零请求代码...要提的至关重要的一点!!!现在工作!谢谢!【参考方案8】:添加android training site 上的通知后,我遇到了类似的问题。这里没有其他答案对我有用,但是 this answer 确实对我有用。总结:
final Intent notificationIntent = new Intent(context, YourActivity.class);
notificationIntent.setAction(Intent.ACTION_MAIN);
notificationIntent.addCategory(Intent.CATEGORY_LAUNCHER);
notificationIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
【讨论】:
以上是关于意图 - 如果活动正在运行,请将其放在前面,否则启动一个新活动(来自通知)的主要内容,如果未能解决你的问题,请参考以下文章