目的-如果活动正在运行,请将其置于最前面,否则(从通知中)开始一个新的活动


129

我的应用程序具有通知,这些通知很明显没有任何标志,每次都启动一个新活动,因此我在彼此之上运行多个相同的活动,这是错误的。

我要执行的操作是将通知待定意图中指定的活动(如果已在运行中)移到最前面,否则将其启动。

到目前为止,我拥有该通知的意图/待定意图是

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);
}

奇怪的是,它有时起作用,有时却不起作用...我感觉我已经尝试了每种标志组合。

Answers:


131

您可以使用此:

<activity 
   android:name=".YourActivity"
   android:launchMode="singleTask"/>

它的工作原理"singleInstance"与之相似,但不会有那种怪异的动画。


15
+1,您应该是被接受的答案。差异是在这里:developer.android.com/guide/topics/manifest/...
user1032613

1
为了明确起见,如果应用程序中有多个活动,并且它是父级,则使用singleTask;如果只有一个活动,则为singleInstance。
frostymarvelous

4
如果像我这样的人在结束本网站之前尝试了多种解决方案组合,请执行以下操作:确保摆脱尝试过的其他更改,并确保对正确的活动进行了更改。花了我太长时间才发现,如果我也没有尝试其他解决方案(例如,覆盖onNewIntent和设置标志),那么该解决方案将
行得通

我有一个Messenger,活动对的地图。如果收到消息,我想显示活动实例。有什么办法做到这一点。例如:HashMap.get(Messenger).bringActivityToFront(); 我的意思是,该活动仍在运行。如果我打开最近的任务并单击它,它将显示onResume();。以编程方式无法实现onResume()。

@JaveneCPPMcGowan似乎完全是一个不同的问题,建议您发布该问题,因为它本身是一个问题,不幸的是我真的不知道答案。
佛朗哥

46

我认为最好的方法是简单地正常启动活动,但要在带有singleInstance属性的清单中设置该活动。这样一来,您几乎可以解决当前遇到的两个问题,方法是始终将活动放在最前面,如果不存在任何活动,则让操作系统自动创建一个新的活动,或者让当前存在的活动放在最前面(感谢singleInstance属性)。

这是将活动声明为单个实例的方式:

<activity 
   android:name=".YourActivity"
   android:launchMode="singleInstance"/>

另外,为了避免在通过singleInstance启动时出现断断续续的动画,您可以改用“ singleTask”,两者非常相似,但根据Google文档在此说明了区别:

<activity 
   android:name=".YourActivity"
   android:launchMode="singleTask"/>

singleInstance与“ singleTask”相同,除了系统不会将任何其他活动启动到保存实例的任务中。活动始终是其任务的唯一且唯一的成员。

希望这可以帮助。

问候!


4
似乎可行,但是现在我从singleIntent MainActivity启动的所有其他新活动,都播放此奇怪的弧光动画,而不是常规的淡入淡出和缩放
urSus 2013年

我每次启动一个新活动但清除所有其他正在运行的实例怎么办?
urSus

好吧,我认为您提到的动画与“ singleInstance”属性无关,它所做的只是重用现有实例,也许您正在谈论的动画是一个完全不同的问题……
Martin Cazares

1
好吧,我现在正在测试它,而且确实可以。如果我删除了所有意图标志并仅在清单中设置了launchMode =“ singleInstance”,就会出现怪异的动画,如果我将其删除,它会恢复正常
urSus 2013年

是的,根据android文档,似乎“ init”动画不再像往常一样在那里,因为活动尚未初始化,只是被重用...
Martin Cazares

26

我认为您需要的是singleTop Activity而不是a singleTask或in singleInstance

<activity android:name=".MyActivity"
          android:launchMode="singleTop"
          ...the rest... >

什么文件说,不完全满足您的需求:

singleTop也可以创建“ ”活动的新实例来处理新的意图。但是,如果目标任务在其堆栈的顶部已经具有该活动的现有实例,则该实例将收到新的意图(在onNewIntent()调用中);没有创建新实例。在其他情况下(例如,如果“ singleTop”活动的现有实例位于目标任务中,但不在堆栈顶部,或者它位于堆栈顶部,但不在目标任务中),则实例将被创建并压入堆栈。

最重要的是(没有双关语),我和您的需求完全一样。我测试了所有launchMode标志,以弄清楚它们在实际中的行为,因此singleTop实际上是最好的:没有奇怪的动画,应用在最近的应用列表中只显示了一次(singleInstance与之不同的是,由于它没有两次显示, t允许任何其他Activity任务作为其任务的一部分),并且无论目标是否Activity存在,都要进行适当的行为训练。


2
工作至周五晚上10点,这就是我想要的...悲伤的开发人员生活。
felixwcf '18

节省了我很多时间!谢谢!
hetsgandhi

13

这是旧线程,但是对于所有仍在寻找答案的人,这是我的解决方案。它完全是代码,没有清单设置:

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将删除目标活动之上的所有活动并显示它。如果活动不在任务堆栈中,则将创建新的活动。要提到的一个至关重要的要点-PendingIntent.getActivity()的第二个参数,即requestCode应该具有非零值(我甚至在代码段中将其称为NON_ZERO_REQUEST_CODE),否则这些intent标志将不起作用。我不知道为什么会这样。标记FLAG_ACTIVITY_SINGLE_TOP可与清单活动标签中的android:launchMode =“ singleTop”互换。


这些小时以来与这些标志的战斗,并想知道为什么更改我的意图标志不会改变任何事情。非零请求代码...一个非常重要的要点!!!现在工作!谢谢!
最大功率

9

我知道它很旧,但是以上内容都不适合我的应用程序。

在不更改清单和其他配置的情况下,以下代码可将您的应用重新带到前面-或在关闭时将其打开

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);

这才是真正的答案!
azizbekian

2
不,这是行不通的-它会在当前活动的顶部添加一个新活动。
Tobliug

3

我尝试了一下,即使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());

2
<activity android:name =“。MainActivity” android:launchMode =“ singleTask”>
nada

Intent.FLAG_ACTIVITY_REORDER_TO_FRONTPendingINtent.getActivity
rds

@rds可以链接源吗?
路易CAD

@LouisCAD对不起,我再也无法访问源代码
nada

@rds我不是在索要源代码,而是在索取您所读到的链接,Intent.FLAG_ACTIVITY_REORDER_TO_FRONT当用作时不是有效的标志PendingIntent。或者,也许您的意思是将其传递给该getActivity方法无效,但可以用作Intent标记,然后将该标记用作PendingIntent??
路易CAD

2

因为您说过您想开始尚未开始的活动,所以也许您不介意重新启动它。我也测试了很多建议和标志组合以达到目的,尽管它不会保留任何先前与之相关的状态,但它总是将您需要的活动置于最前面。

intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK|Intent.FLAG_ACTIVITY_NEW_TASK);

仅API11 +。


0

添加了android培训网站上的通知后,我遇到了类似的问题。这里没有其他答案对我有用,但是这个答案对我有用。摘要:

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);
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.