Android - 清除任务标志不适用于PendingIntent

时间:2014-07-21 19:28:28

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

我有一个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中是不可能的,或者在使用待处理的意图时是不可能的。

编辑2: 这不是需要什么标志的问题。更多的问题可能是错误,标志似乎没有效果。

9 个答案:

答案 0 :(得分:15)

如果你使用解决方案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);

OR

2)

       <activity 
       android:name=".ActivityA" 
       android:theme="@style/theme_noActionBar" 
       android:noHistory="true">

OR

3)

<activity android:name=".ActivityA" android:launchMode="singleTop">

答案 1 :(得分:5)

您遇到的问题与Android使用PendingIntent和所需的Intent.FLAG_ACTIVITY_NEW_TASK创建新任务有关。换句话说,您想要使用的标志与在给定任务堆栈的上下文中启动活动有关。 PendingIntent通常没有上下文,因此您看到的是为您的活动A挂起的意图创建的任务。

以下是对文档的引用:

Android PendingIntent

要求PendingIntent系列Intent.FLAG_ACTIVITY_NEW_TASK中的第一个要求TaskStackBuilder。请注意,使用“getActivities”方法,一系列待处理意图可以与初始待处理意图具有相同的上下文。

你是对的,你不可能只使用旗帜做你想做的事。您的代码是正确的,并且为了获得您想要的行为,您还需要超越意图标记。

还有许多其他方法,例如使用清单,运行服务,使用静态字段等来尝试管理您感兴趣的内容。除此之外,如果您决定使用Manifest,您可以使用{{1}}来解决您的问题。还有许多其他不涉及标志的解决方案,但您特别询问了使用标志。

答案 2 :(得分:4)

您可以在Manifest文件中将ActivityA的launchMode设置为singleTask。由于ActivityA是您的应用程序的根,因此可以使用。

来自documentation

  

系统在新任务和路由的根目录下创建活动   意图。但是,如果活动的实例已经存在   存在,系统通过a将意图路由到现有实例   调用它的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);

答案 3 :(得分:3)

我遇到了很多这样的问题,并且在我卸载/重新安装我的应用程序之前我觉得自己很疯狂,并且嘿presto,代码按照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);

并且不断获得两个版本的App。在一台设备上卸载并重新启动另一台设备后,现在所有内容都会按照预期的单一实例运行。希望这会对你有所帮助。

答案 4 :(得分:2)

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

  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);
    
  3. 这里发生的事情是,当使用通知启动活动A时,通过Intent.FLAG_ACTIVITY_NEW_TASK的定义,由于存在包含A的任务A&gt; B&gt; C,此任务也被提前破坏活动B和C和A以onNewIntent --> onRestart --> onStart --> onResume

    开头
      

    如果某个任务已在您正在启动的活动中运行,则该任务将恢复到前台并恢复其上一个状态,并且该活动将在onNewIntent()

    中接收新的意图

    现在的原因是,为什么它仅仅与意图标志表现不佳就是,活动A没有以singleTask模式启动,而Android在某种程度上不能维持它的状态。

答案 5 :(得分:1)

尝试使用Intent标志FLAG_ACTIVITY_CLEAR_TOP而不是清除任务。来自Intent documentation

  

如果设置,则正在启动的活动已在运行中   当前任务,然后而不是启动它的新实例   活动,其上的所有其他活动将被关闭   这个意图将作为一个传递到(现在在顶部)旧活动   新的意图。

     

例如,考虑一个由活动组成的任务:A,B,C,D。   如果D调用带有解析为的Intent的startActivity()   活动B的组成部分,然后C和D将完成,B接收   给定的Intent,导致堆栈现在为:A,B。

答案 6 :(得分:1)

我创建了一个演示项目作为您的描述,它可以像您想要的那样工作。

我不知道你是如何得到通知的,所以在我的项目中我使用BroadcastReceiver获取广播,然后在Receiver的onReceive()方法中显示Notification。我认为您可以将我的演示与您的项目进行比较以找到问题。顺便说一句,我的测试是在API 16下进行的。

这是我的演示: https://github.com/leoguo123/AndroidDemo

在存储库中:

测试项目包含3个活动(A&gt; B&gt; 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);
    }
}

答案 7 :(得分:1)

我的解决方案代码:

    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 :(得分:0)

从上面尝试了所有建议,但都失败了,并从https://stackoverflow.com/a/24999724/4271334https://stackoverflow.com/a/26592562/4271334的指南中提出了解决方案。 在清单中添加了以下两行

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

希望有人会得到帮助。