Android - 清除任务标志不适用于 PendingIntent
Posted
技术标签:
【中文标题】Android - 清除任务标志不适用于 PendingIntent【英文标题】:Android - Clear task flag not working for PendingIntent 【发布时间】:2014-09-12 10:22:56 【问题描述】:我有一个 A > B > C 的任务堆栈。我目前在 C 上,然后我按下主页按钮。我收到一条通知,打算将我带到活动 A。我按下通知,我在 A,但如果我按回去,我转到 C,然后是 B,然后是 A。
我正在像这样设置我的 PendingIntent。有什么明显的问题吗?
final Intent notificationIntent = new Intent(mContext, ActivityA.class);
notificationIntent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK | Intent.FLAG_ACTIVITY_NEW_TASK);
PendingIntent contentIntent = PendingIntent.getActivity(myContext, 0, notificationIntent, 0);
编辑 1:
我在这里尝试了这个建议:Clear all activities in a task?
notificationIntent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_ACTIVITY_SINGLE_TOP | Intent.FLAG_ACTIVITY_CLEAR_TASK | Intent.FLAG_ACTIVITY_NEW_TASK);
但我仍然得到相同的结果。我的活动 A 在我的应用程序任务堆栈中开始,我按下返回并转到 C,然后是 B,然后是 A。
我开始认为这在 android 中是不可能的,或者在使用挂起的 Intent 时是不可能的。
编辑 2: 这不是需要什么标志的问题。更多的问题是标志似乎没有效果。
【问题讨论】:
明确地说,您想返回 A 并从堆栈中删除 B 和 C? 我想返回 A 并删除 B 和 C,但我不确定我是否只是希望 A 恢复或 A 也被删除,并启动 A 的新实例。 @DanS 无论哪种方式。我需要清除 B 和 C。当我可以进行清算时,我会检查 A 的行为。 在ActivityA
中你有onNewIntent()
实现了吗?
@DanS 不。我还没有听说过这种方法,但我想专注于从堆栈中正确清除 B 和 C。
【参考方案1】:
如果您使用解决方案 1,那么只需从清单中删除 launchMode="singleTask"
1)
final Intent notificationIntent = new Intent(mContext, ActivityA.class);
notificationIntent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_ACTIVITY_SINGLE_TOP | Intent.FLAG_ACTIVITY_CLEAR_TASK | Intent.FLAG_ACTIVITY_NEW_TASK);
PendingIntent contentIntent = PendingIntent.getActivity(myContext, 0, notificationIntent, 0);
或
2)
<activity
android:name=".ActivityA"
android:theme="@style/theme_noActionBar"
android:noHistory="true">
或
3)
<activity android:name=".ActivityA" android:launchMode="singleTop">
【讨论】:
选项 2 对我有用,选项 1 在我的情况下根本没有帮助 选项 2 为我唤醒了 仅当 Intent 具有非空操作时,选项 1 才适用于我。为什么?! ...或者当PendingIntent
具有非零requestCode
。
卸载并重新安装该应用程序使 OP 的原始代码对我有用,正如以下晦涩的答案之一所建议的那样 (CLEAR_TOP | NEW_TASK)【参考方案2】:
我在这方面遇到了很多问题,并认为我要疯了,直到我卸载/重新安装了我的应用程序,嘿,很快,代码按照 Stack Overflow 上的许多帖子工作。我正在执行以下操作:
Intent i = new Intent(getApplicationContext(), MainActivity.class);
i.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_ACTIVITY_SINGLE_TOP);
PendingIntent pi = PendingIntent.getActivity(this, 0, i, 0);
并且不断获得该应用程序的两个版本。在一台设备上卸载并重新启动另一台设备后,现在所有的行为都与单个实例的预期一样。希望对您有所帮助。
【讨论】:
我的也需要重启才能使新的 Intent.FLAG_ACTIVITY_CLEAR_TOP 工作! 遗留答案永远不会过时! :D 它也让我发疯,重新启动应用程序是它工作的原因。非常感谢分享这个。 是的 卸载并重新安装解决了我的问题。【参考方案3】:您遇到的问题与 Android 使用您的 PendingIntent
和所需的 Intent.FLAG_ACTIVITY_NEW_TASK
创建新任务有关。换句话说,您要使用的标志与在给定任务堆栈的上下文中启动活动有关。 PendingIntent
通常没有上下文,因此您看到的是正在为您的 Activity A 未决意图创建的任务。
这是对文档的参考:
Android PendingIntent
要求PendingIntent
s 系列中的第一个具有Intent.FLAG_ACTIVITY_NEW_TASK
是问题所在。请注意,一系列待处理的意图可以与使用“getActivities”方法的初始待处理意图具有相同的上下文。
你说得对,只使用标志是不可能做你想做的事的。您的代码是正确的,要获得您想要的行为,您还需要超越意图标志。
还有很多其他方式,比如使用清单、运行服务、使用静态字段等来尝试管理您感兴趣的事情。除此之外,如果您决定走使用 Manifest 的路线,您可以使用TaskStackBuilder
来解决您的问题。还有很多其他不涉及标志的解决方案,但是您专门询问了使用标志的问题。
【讨论】:
【参考方案4】:您可以在Manifest文件中将ActivityA的launchMode
设置为singleTask
。因为ActivityA
是你的应用程序的根,所以它可以工作。
来自documentation:
系统在新任务和路由的根目录创建活动 它的意图。但是,如果活动的一个实例已经 存在,系统通过 调用它的 onNewIntent() 方法,而不是创建一个新方法。
<activity
android:name=".MainActivity"
android:label="@string/app_name"
android:launchMode="singleTask" >
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
编辑 1:
由于您不想修改 Manifest 文件,我能看到的唯一选项是使用 Intent.makeRestartActivityTask 方法生成 Intent。但是,这将重新启动 ActivityA 而不是恢复现有实例。
Intent intent = Intent.makeRestartActivityTask(new ComponentName(this, ActivityA.class));
PendingIntent rIntent = PendingIntent.getActivity(getApplicationContext(), 0, intent, 0);
【讨论】:
这可以工作,但如果我想将我的待定意图更改为活动 B,那么设置单个任务会给我带来问题。我应该能够在不修改清单的情况下设置一个 Intent.FLAG 来执行此操作。makeRestartActivityTask
就像一个魅力!谢谢
我不知道为什么,但这是唯一适合我的选择。我有一个期望结果的外部应用程序启动的活动,并在我自己的应用程序中使用 NFC + 挂起意图,这完全破坏了我的应用程序在我只使用 NEW_TASK 时所做的结果设置。【参考方案5】:
意图标志的解决方案如下:
-
在 Manifest 中,为活动 A 添加
launchMode:singleTask
使用以下代码块:
final Intent notificationIntent = new Intent(mContext, ActivityA.class);
notificationIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
PendingIntent contentIntent = PendingIntent.getActivity(myContext, 0, notificationIntent, 0);
这里发生的情况是,当使用通知启动 Activity A 时,根据Intent.FLAG_ACTIVITY_NEW_TASK
的定义,由于存在一个包含 A 的任务 A>B>C,因此该任务被提出,同时破坏了活动 B 和 C 并且A以onNewIntent --> onRestart --> onStart --> onResume
开头
如果您现在正在启动的 Activity 的任务已在运行,则该任务将被带到前台并恢复其最后状态,并且该 Activity 在
onNewIntent()
中接收新意图
现在的原因是,仅使用 Intent 标志时它表现不佳的原因是,Activity A 不是以 singleTask
模式启动的,并且 Android 不知何故无法保持它的状态。
【讨论】:
【参考方案6】:尝试使用 Intent 标志 FLAG_ACTIVITY_CLEAR_TOP
而不是清除任务。来自Intent documentation:
如果设置,并且正在启动的活动已经在 当前任务,而不是启动该任务的新实例 活动,其之上的所有其他活动都将关闭,并且 此 Intent 将作为 新意图。
例如,考虑由以下活动组成的任务:A、B、C、D。 如果 D 调用 startActivity() 的 Intent 解析为 活动B的组成部分,然后C和D将完成,B收到 给定的 Intent,导致堆栈现在是:A,B。
【讨论】:
刚试过。与我的问题中提到的行为相同。【参考方案7】:我的解决方案代码:
public class MyApplication extends Application
private static int activityCounter;
public Activity A,B,C;
public void incrementActivityCounter()
activityCounter++;
public void decrementActivityCounter()
activityCounter--;
if (activityCounter == 0)
A.finish();
B.finish();
C.finish();
public class A extends Activity
@Override
protected void onStart()
super.onStart();
application.incrementActivityCounter();
@Override
protected void onStop()
application.decrementActivityCounter();
super.onStop();
【讨论】:
【参考方案8】:我创建了一个演示项目作为您的描述,它可以按照您的要求工作。
我不知道你是怎么得到通知的,所以在我的项目中我使用了一个BroadcastReceiver来获取一个Broadcast,然后在Receiver的onReceive()方法中显示这个Notification。我认为您可以将我的演示与您的项目进行比较以找出问题所在。顺便说一句,我的测试是在 API 16 下进行的。
这是我的演示: https://github.com/leoguo123/AndroidDemo
在存储库中:
测试项目包含 3 个 Activity(A > B > C),它可以在收到正确的广播时显示通知。 SendBroadcast 项目负责发送广播。
生成通知的代码:
public class MyBroadcastReceiver extends BroadcastReceiver
@Override
public void onReceive(Context context, Intent intent)
showNotification(context);
private void showNotification(Context context)
Intent intent = new Intent(context, ActivityA.class);
intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP
| Intent.FLAG_ACTIVITY_SINGLE_TOP
| Intent.FLAG_ACTIVITY_NEW_TASK);
NotificationManager nmr = (NotificationManager) context
.getSystemService(Context.NOTIFICATION_SERVICE);
PendingIntent pi = PendingIntent.getActivity(context, 0, intent, 0);
Notification.Builder builder = new Notification.Builder(context);
builder.setContentTitle("Open A with B and C being closed");
builder.setContentText("Open A with B and C being closed");
builder.setSmallIcon(R.drawable.ic_launcher);
builder.setContentIntent(pi);
builder.setAutoCancel(true);
Notification nt = builder.build();
nmr.notify(0, nt);
【讨论】:
【参考方案9】:尝试了上面的所有建议但都失败了,并从https://***.com/a/24999724/4271334 和https://***.com/a/26592562/4271334 的指南中找到了解决方案。 在清单中添加以下 2 行
android:launchMode="singleTask"
android:clearTaskOnLaunch="true"
并使用
在 NotificationCompat.Builder 设置 PendingIntentmBuilder.setContentIntent(addBackStack(mContext,intent));
在哪里
public static PendingIntent addBackStack(final Context context, final Intent intent)
TaskStackBuilder stackBuilder = TaskStackBuilder.create (context.getApplicationContext ());
stackBuilder.addNextIntentWithParentStack (intent);
intent.addFlags (Intent.FLAG_ACTIVITY_NEW_TASK);
return stackBuilder.getPendingIntent (0,PendingIntent.FLAG_UPDATE_CURRENT);
希望有人能得到帮助。
【讨论】:
以上是关于Android - 清除任务标志不适用于 PendingIntent的主要内容,如果未能解决你的问题,请参考以下文章
Gradle Maven 插件“安装”任务不适用于 Android 库项目