意图 - 如果活动正在运行,请将其置于最前面,否则启动一个新的(来自通知)

时间:2013-09-26 21:39:46

标签: android android-intent android-activity android-pendingintent

我的应用程序有通知,显然 - 没有任何标记,每次都会启动一个新活动,所以我得到多个相同的活动在彼此之上运行,这是错误的。

我想要它做的是将通知待处理意图中指定的活动带到前面(如果它已经在运行),否则启动它。

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

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

奇怪的是,它有时会起作用,有时它不会......我觉得我已经尝试了每一个标志组合。

8 个答案:

答案 0 :(得分:118)

您可以使用:

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

将与"singleInstance"类似,但它不会有那种奇怪的动画。

答案 1 :(得分:38)

我认为以最简单的方式执行此操作的最佳方法是正常启动活动,但在清单中使用singleInstance属性设置该活动。通过这种方式,您实际上可以通过将活动始终放在前面来解决您现在遇到的两个问题,并且如果没有活动则让操作系统自动创建一个新的活动,或者将当前存在的活动带到前面(感谢singleInstance财产)。

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

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

另外为了避免在通过singleInstance启动时出现波动的动画,你可以使用“singleTask”,两者都非常相似,但这里的差异按照Google的文档说明:

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

singleInstance与“singleTask”相同,但系统除外   没有启动任何其他活动进入持有的任务   实例。活动始终是其唯一的成员   任务。

希望这有帮助。

问候!

答案 2 :(得分:24)

我认为您需要的是singleTop Activity,而不是singleTasksingleInstance

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

the documentation says完全符合您的需求:

  

[...]&#34; singleTop&#34;的新实例也可以创建活动来处理   一个新的意图。但是,如果目标任务已经存在   在其堆栈顶部的活动的实例,该实例将   收到新意图(在onNewIntent()电话中);一个新的实例是   没有创建。在其他情况下 - 例如,如果存在   &#34; singleTop&#34;的实例活动在目标任务中,但不在   堆栈的顶部,或者如果它位于堆栈的顶部,但不在堆栈的顶部   目标任务 - 将创建一个新实例并将其推送到堆栈中。

除此之外(没有双关语),我和你有着完全相同的需求。我测试了所有launchMode标志,以确定它们在实践中的实际行为,因此singleTop实际上是最好的:没有奇怪的动画,应用程序在最近的应用程序列表中显示一次(不像{ {1}}由于它不允许任何其他singleInstance成为其任务的一部分而显示两次,并且无论目标Activity是否已存在,都是正确的。

答案 3 :(得分: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);

答案 4 :(得分:3)

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

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”互换 在清单中的活动标签中。

答案 5 :(得分:2)

既然你说你想要开始你的活动,如果它还没有开始,也许你不会介意重新启动它。我为这个意图测试了大量的建议和标志组合,这将始终将您需要的活动带到前面,尽管它不会保留以前与之相关的任何状态。

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

仅限API11 +。

答案 6 :(得分:1)

我试过这个,即使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());

答案 7 :(得分:0)

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