Android - Clear task flag not working for PendingIntent

13,266

Solution 1

if u r using solution 1 then Just remove the launchMode="singleTask" from manifest

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">

Solution 2

I had loads of problems with this, and thought I was going crazy until I uninstalled/reinstalled my App and hey presto, the code works as per many posts on Stack Overflow. I was doing the following:

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

and was continually getting two versions of the App. After an uninstall on one device, and re-starting the other device everything now behaves as expected with a single instance. Hope this helps you.

Solution 3

The problem you are encountering has to do with Android creating a new task using your PendingIntent and the required Intent.FLAG_ACTIVITY_NEW_TASK. In other words, the flags you are wanting to use have to do with starting activities within the context of a given task stack. A PendingIntent usually does not have a context, and therefore what you are seeing is a task being created for your Activity A pending intent.

Here's the reference to the docs:

Android PendingIntent

The requirement for the first in a series of PendingIntents to have Intent.FLAG_ACTIVITY_NEW_TASK is the issue. Note that a series of pending intents can have the same context as the initial pending intent using the "getActivities" method.

You are correct that it is not possible to do what you want only using flags. Your code is correct, and to get the behavior that you want you will need too look beyond intent flags.

There are many other ways, such as using the manifest, running a service, using static fields, etc. to try to manage what you are interested in doing. Besides that, you could possibly use TaskStackBuilder to solve your problem if you decide to go the route of using the Manifest. There are also many other solutions not involving flags, but you specifically asked about using flags.

Solution 4

You can set the launchMode of ActivityA to singleTask in Manifest file. Since ActivityA is the root of your application it works.

From documentation:

The system creates the activity at the root of a new task and routes the intent to it. However, if an instance of the activity already exists, the system routes the intent to existing instance through a call to its onNewIntent() method, rather than creating a new one.

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

EDIT 1:

Since you don't want to modify Manifest file, only option I can see is using Intent.makeRestartActivityTask method to generate the Intent. However this will relaunch the ActivityA rather than resuming existing instance.

Intent intent = Intent.makeRestartActivityTask(new ComponentName(this, ActivityA.class));
PendingIntent rIntent = PendingIntent.getActivity(getApplicationContext(), 0, intent, 0);

Solution 5

A solution in terms of intent flag would be as following:

  1. In Manifest, add launchMode:singleTask for Activity A
  2. Use the following code block:

    final Intent notificationIntent = new Intent(mContext, ActivityA.class);
    notificationIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
    PendingIntent contentIntent = PendingIntent.getActivity(myContext, 0, notificationIntent, 0);
    

What happens here is that when Activity A is launched using notification, by the definition of Intent.FLAG_ACTIVITY_NEW_TASK, since there exists a task A>B>C containing A, this task is brought forward also destroying the activities B and C and A starts with the onNewIntent --> onRestart --> onStart --> onResume

If a task is already running for the activity you are now starting, that task is brought to the foreground with its last state restored and the activity receives the new intent in onNewIntent()

Now the reason, why it doesn't behave nicely with just the intent flags is that, the Activity A wasn't launched with singleTask mode and Android somehow doesn't maintain the state of it.

Share:
13,266

Related videos on Youtube

Admin
Author by

Admin

Updated on October 01, 2022

Comments

  • Admin
    Admin over 1 year

    I have a task stack of A > B > C. I am currently on C, and then I press the home button. I get a notification with the intent to take me to Activity A. I press the notification, and I'm at A but if I press back, I go to C, then B, then A.

    I am setting up my PendingIntent like so. Anything clearly wrong with it?

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

    EDIT 1:

    I tried the suggestion here: 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);
    

    but I still get the same result. My activity A starts in my application task stack, I press back and go to C, then B, then A again.

    I am starting to think that this is either not possible in Android or it's not possible when using a pending intent.

    EDIT 2: This is not a matter of what flags are needed. More of an issue of what could be going wrong that the flags seem to have no effect.

    • Dan S
      Dan S over 9 years
      To be clear you want to return to A with B and C removed from the stack?
    • Admin
      Admin over 9 years
      I want to return to A with B and C removed, but I'm not sure if I just want A to resume or A to be removed as well, and a new instance of A to start.
    • Admin
      Admin over 9 years
      @DanS either way. I NEED B and C to be cleared. I will inspect the behavior of A when I can get the clearing to happen.
    • Dan S
      Dan S over 9 years
      In ActivityA do you have onNewIntent() implemented?
    • Admin
      Admin over 9 years
      @DanS Nope. I haven't heard of that method, but I'd like to focus on clearing B and C properly from the stack.
    • Dan S
      Dan S over 9 years
      That method will be called to handle the formerly pending Intent. Try a simple implementation to see if that will fix your stack problem.
    • Admin
      Admin over 9 years
      @DanS Sorry. Can you elaborate by "try a simple implementation"?
    • Dan S
      Dan S over 9 years
    • matiash
      matiash over 9 years
      @user2676468 Just to clarify, have you tried the NEW_TASK | CLEAR_TOP combination, with no other flags?
    • Admin
      Admin over 9 years
      Yes. I got the same behavior as mentioned in my question.
    • Vaishali Sutariya
      Vaishali Sutariya over 9 years
      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);
    • Vaishali Sutariya
      Vaishali Sutariya over 9 years
      @user2676468 thank you :)
    • Jim
      Jim over 9 years
      Have the same issue, did you found a solution ?
    • Admin
      Admin over 9 years
      @Jim nope. Still super confused how this doesn't seem to be possible.
    • user2297550
      user2297550 about 5 years
      Strangely enough, uninstalling and reinstalling the app made the original code work (CLEAR_TOP | NEW_TASK), as suggested by one of the obscure answers to this question below. If you can confirm it, please accept it to save a lot of people a lot of trouble.
  • Admin
    Admin over 9 years
    Just tried it. Same behavior as mentioned in my question.
  • Admin
    Admin over 9 years
    This could work, but in case I ever wanted to change my pending intent to Activity B, then setting single task would give me an issue. I should be able to set an Intent.FLAG to do this without modifying the manifest.
  • Newtz
    Newtz over 8 years
    Option 2 worked for me, option 1 didn't help at all in my situation
  • ashraful
    ashraful over 6 years
    Option 2 woked for me
  • Miha_x64
    Miha_x64 almost 6 years
    Option 1 works for me only when Intent has non-null action. Why?!
  • Miha_x64
    Miha_x64 almost 6 years
    ...or when PendingIntent has non-zero requestCode.
  • Vlad
    Vlad over 5 years
    makeRestartActivityTask works like a charm! Thanks
  • user2297550
    user2297550 about 5 years
    uninstalling and reinstalling the app made the OP's original code work for me, as suggested by one of the obscure answers below (CLEAR_TOP | NEW_TASK)
  • Daniel Wilson
    Daniel Wilson over 4 years
    I don't know why but this is the only option that works for me. I have an activity launched by an external app expecting a result, and use NFC + pending intents in my own app which was totally breaking the result setting my app does when I just use NEW_TASK.
  • Flyview
    Flyview about 4 years
    Mine also needed a restart for the new Intent.FLAG_ACTIVITY_CLEAR_TOP to work!
  • Harmen
    Harmen almost 4 years
    Method 3 did it for me.
  • Houssem Chlegou
    Houssem Chlegou over 3 years
    legacy answers never gets old! :D it drive me crazy also, and restarting the app is what made it working. Thanks a lot for sharing this.
  • uzaysan
    uzaysan over 3 years
    Yes Uninstalling and reinstalling solved my problem.
  • mehul bisht
    mehul bisht about 2 years
    non-zero request code did it for me! :)