【问题标题】:Android - Clear task flag not working for PendingIntentAndroid - 清除任务标志不适用于 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。

标签: android android-intent android-notifications android-pendingintent


【解决方案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

要求PendingIntents 系列中的第一个具有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】:

    意图标志的解决方案如下:

    1. 在 Manifest 中,为活动 A 添加 launchMode:singleTask
    2. 使用以下代码块:

      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 --&gt; onRestart --&gt; onStart --&gt; 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://stackoverflow.com/a/24999724/4271334https://stackoverflow.com/a/26592562/4271334 的指南中找到了解决方案。 在清单中添加以下 2 行

          android:launchMode="singleTask"
          android:clearTaskOnLaunch="true"
          

          并使用

          在 NotificationCompat.Builder 设置 PendingIntent
          mBuilder.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);
          }
          

          希望有人能得到帮助。

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2019-11-21
            • 2014-02-27
            • 1970-01-01
            • 1970-01-01
            相关资源
            最近更新 更多