意图-如果活动正在运行,将其放在前面,否则启动一个新的(通知)

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

我希望它做的是将通知中指定的活动挂起意图,如果它已经在运行,则放在前面,否则启动它。

到目前为止,通知的意图/待定意图是

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

奇怪的是,有时候管用,有时候不管用... 我觉得我已经尝试过所有旗帜的组合了。

86204 次浏览

我认为最好的方法是以一种简单的方式正常地启动活动,但是使用 singleInstance属性在清单中设置该活动。通过这种方式,你实际上可以解决你现在所面临的两个问题,一个是一直将活动放在前面,另一个是让操作系统在没有活动的情况下自动创建一个新的活动,或者将当前已有的活动放在前面(感谢 singleInstance属性)。

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

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

另外,为了避免在通过 singleInstance 启动时出现断断续续的动画,你可以使用“ singleTask”来代替,两者非常相似,但是根据 Google 的文档解释了它们的区别:

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

SingleInstance 与“ singleTask”相同,只是系统 不会在任务中启动任何其他活动 活动始终是其 任务。

希望这个能帮上忙。

问候!

你可以用这个:

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

它的工作原理类似于 "singleInstance"但不会有那种奇怪的动画。

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

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

只限 API11 + 。

我认为你需要的是在 singleTop Activity,而不是一个 singleTasksingleInstance

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

文件上说完全适合你的需要:

[ ... ]也可以创建一个新的“ singleTop”活动实例来处理 但是,如果目标任务已经有一个现有的 活动的堆栈顶部的实例,该实例将 接收新意图(在 onNewIntent()调用中) ; 新实例是 在其他情况下ーー例如 “ singleTop”活动的实例在目标任务中,但不在 堆栈的顶部,或者如果它位于堆栈的顶部,但不在 目标任务ーー将创建一个新实例并将其推送到堆栈上。

最重要的是(没有双关语的意思) ,我和你有完全相同的需要。我测试了所有的 launchMode标志来弄清楚它们在实践中的实际行为,结果 singleTop实际上是最好的: 没有奇怪的动画,应用程序在最近的应用程序列表中显示一次(不像 singleInstance显示两次,因为它不允许任何其他 Activity成为其任务的一部分) ,正确的行为不管目标 Activity是否已经存在。

我尝试了这种方法,即使 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 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);

这是老生常谈了,但是对于所有那些仍然在寻找答案的人,这里是我的解决方案。它纯粹是在代码中,没有清单设置:

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 将删除目标活动顶部的所有活动并显示它。如果活动不在任务堆栈中,将创建新的活动。提到 PendingInent.getActivity ()的第二个参数非常重要,即 requestCode 应该具有非零值(在我的代码片段中我甚至称之为 NON _ ZERO _ REQUEST _ CODE) ,否则这些意图标志将无法工作。我不知道为什么会这样。标志 FLAG _ ACTIVITY _ SINGLE _ TOP 可与 android 互换: launchMode = “ singleTop” 在活动标记的清单。

在添加了 机器人训练基地上的通知之后,我也遇到了类似的问题。这里的其他答案都不适合我,但是 这个答案确实适合我。摘要:

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