Clear all activities in a task? - android

I have a splash screen activity, then a login activity. My history stack looks like:
SplashActivity
LoginActivity
when the user successfully logs in via LoginActivity, I want to start WelcomeActivity, but clear the entire stack:
SplashActivity
LoginActivity // launches WelcomeActivity ->
WelcomeActivity
// but now all three are in the history stack, while I only
// want WelcomeActivity in the stack at this point.
Is there some flag I can use to do that?
// LoginActivity.java
Intent intent = new Intent(this, WelcomeActivity.class);
intent.addFlag(Intent.FLAG_ACTIVITY_CLEAR_TASK);
startActivity(intent);
finish();
Not sure if using the FLAG_ACTIVITY_CLEAR_TASK will clear out all activities in my task or not. I can do this 'manually' by unwinding the stack by using startActivityForResult() calls, but will be more fragile and more code to maintain.
Thanks

Yes that should work fine. You could use:
FLAG_ACTIVITY_CLEAR_TOP
FLAG_ACTIVITY_SINGLE_TOP
FLAG_ACTIVITY_CLEAR_TASK
FLAG_ACTIVITY_NEW_TASK
which ensures that if an instance is already running and is not top then anything on top of it will be cleared and it will be used, instead of starting a new instance (this useful once you've gone Welcome activity -> Activity A and then you want to get back to Welcome from A, but the extra flags shouldn't affect your case above).

Intent intent = new Intent(this, NextActivity.class);
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK |
IntentCompat.FLAG_ACTIVITY_CLEAR_TASK);
startActivity(intent);

Use android:noHistory="true" on the splash activity in the manifest file.
<activity
android:name=".activity.SplashActivity"
android:theme="#style/theme_noActionBar"
android:noHistory="true">

finish() removes the activity from the stack. So, if you start LoginActivity and call finish() on SplashActivity, and then you do exact the same to start WelcomeActivity you will get the desired behaviour. No need to use extra flags.

Intent.FLAG_ACTIVITY_NO_HISTORY can work in your case too if you do not want the activity on the history stack.

Just do this to clear all previous activity in a task:
finishAffinity() // if you are in fragment use activity.finishAffinity()
Intent intent = new Intent(this, DestActivity.class); // with all flags you want
startActivity(intent)

In case that all of three activity is involved in the same app(same taskAffinity), you can pick either 1,2 or 3 below. otherwise you should pick 1,2 below.
If you don't want to return back SplashActivity from LoginActivity, you can define activity attribute noHistory in AndroidManifest.xml or you can set FLAG_ACTIVITY_NO_HISTORY into the intent to launch SplashActivity. if SplashActivity is started from Launcher, you should pick way to set activity attribute noHistory.
If you don't want to return back LoginActivity from WelcomeActivity, you can use either activity attribute noHistory or FLAG_ACTIVITY_NO_HISTORY like number 1 above.
If you want to clear back stack on specific situation, you can use FLAG_ACTIVITY_CLEAR_TASK in conjunction with FLAG_ACTIVITY_NEW_TASK(FLAG_ACTIVITY_CLEAR_TASK always must be used in conjunction with FLAG_ACTIVITY_NEW_TASK). But, if the activity being started is involved in other app(i.e different taskAffinity), the task will be launched other task after the task is cleared, not current task. so make sure that the activity being launched is involved in the same app(taskAffinity).

Related

Should I use FLAG_ACTIVITY_CLEAR_TOP in this case? how to use FLAG_ACTIVITY_CLEAR_TOP intent flag?

In my app I have the following Activity flow:
LoginActivity > DashboardActivity > (if user opts to change their password) > ChangePasswordActivity
If the user successfully changes their password, I'd like to send them back to the very first Activity which is LoginActivity. I would like to pop DashboardActivity in the process to prevent any unwanted lingering Activities.
Is it correct to use FLAG_ACTIVITY_CLEAR_TOP to start a new LoginActivity in this case? I'd like to know which flags are appropriate in this scenario.
For what it's worth, my DashboardActivity has a launchMode set to singleTop in my AndroidManifest.
If you want to just clear the previous activities from stack and
launch login activity just do this
in manifest file your login activity should be like this
<activity
android:name=".LoginActivity"
android:screenOrientation="portrait"/>
After changing password launch the login activity with following tags
Intent intent = new Intent(ChangePassword.this, LoginActivity.class);
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK);
startActivity(intent);
finish();
By setting flag to Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK
all the previous activities will be cleared from stack.
for more info check this
https://developer.android.com/reference/android/content/Intent
From the official documentation - FLAG_ACTIVITY_CLEAR_TOP
If set, and the activity being launched is already running in the
current task, then instead of launching a new instance of that
activity, all of the other activities on top of it will be closed and
this Intent will be delivered to the (now on top) old activity as a
new Intent.
For example, consider a task consisting of the activities: A, B, C, D.
If D calls startActivity() with an Intent that resolves to the
component of activity B, then C and D will be finished and B receive
the given Intent, resulting in the stack now being: A, B.
LoginActivity > DashboardActivity > (if user opts to change their password) > ChangePasswordActivity
In order to clear task and intent to LoginActivty you should use
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK);
Is it correct to use FLAG_ACTIVITY_CLEAR_TOP to start a new LoginActivity in this case? I'd like to know which flags are appropriate in this
FLAG_ACTIVITY_CLEAR_TOP will clear everything from the stack and make
the new activity as root task. In your case, there is no previous
activity for LoginActivity it will also work but not advisable.
For what it's worth, my DashboardActivity has a launchMode set to singleTop in my AndroidManifest.
It will not be useful in your case though you get detail of “LaunchMode" here https://blog.mindorks.com/android-activity-launchmode-explained-cbc6cf996802
Also check
https://blog.mindorks.com/android-task-and-back-stack-review-5017f2c18196
for details

When do I use addFlags or setFlags for the purpose of removing activities in stack?

I have OnBoard Activity and Login Activity. In LoginActivity after successful login I am trying to clear onboard activity using below code:
startActivity(new Intent(context, HomeActivity.class).addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP|Intent.FLAG_ACTIVITY_CLEAR_TASK));
I've even tried Intent.FLAG_ACTIVITY_NO_HISTORY but it's also not working. So what should I do?
I am assuming that the app starts with OnboardActivity and that starts LoginActivity and then you want to clear them both and launch HomeActivity?
If that is the case, I would do it this way:
OnboardActivity launches LoginActivity using startActivityForResult().
LoginActivity returns a result that indicates if the login was successful or not and calls finish(). LoginActivity is no longer in the task.
OnboardActivity checks the result in OnActivityResult() and, if the login was successful, launches HomeActivity (no flags needed) and calls finish() on itself.
At this point, both LoginActivity and OnboardActivity are gone, and HomeActivity is the only Activity in the task.
Try below code:
Intent intent = new Intent(context, HomeActivity.class);
intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_ACTIVITY_NEW_TASK);
intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK);
startActivity(intent);
I would say go with the finishAffinity() before moving to onboard activity. There is no need to set any flags. Because this method kills all activities in the stack and current activity as well
There is no need to use FLAGS. Even though you want to understand, Check this
There are two ways to finish Current Activity (LoginActivity in your case) and move to Next Activity (OnBoard in your case).:
Call finish() before starting Second Activity. It will destroy current activity.
Call finishAffinity(); before starting Second Activity. It will destroy stack of all previous activity.
Hope it will helps you.

How to come back to First activity without its onCreate() called

I have 3 activity . Activity A ,Activity B, Activity C.
This is the flow A->B->C.
Now i want to come to activity A from C .(i.e C->A) without getting its onCreate() called of Activity A.
so far my code is:But it will call onCreate() of ActivityA.
I want to call Restart().
Intent intent=new Intent(ActivityC.this,ActivityA.class);
intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
startActivity(intent);
finish();
Two cases:
If you want to keep other activities live and just want to bring A to front, just use intent flag FLAG_ACTIVITY_REORDER_TO_FRONT.
If you don't want to clear all activities and want existing instance of A at top, then use intent flags FLAG_ACTIVITY_CLEAR_TOP and FLAG_ACTIVITY_SINGLE_TOP.
Note : If you use only FLAG_ACTIVITY_CLEAR_TOP, then onCreate will be called.
Keep android:launchMode="singleTask" in manifest at activity declaretion
An Activity with singleTask launchMode is allowed to have only one instance in the system
If instance already exists, i will not call 'onCreate' it will call 'onNewIntent' method.
See http://androidsrc.net/android-activity-launch-mode-example/ for better understand about launch modes.
Although setting the launch mode to singleTask will work, use of that launch mode is discouraged. The documentation for launch mode indicates singleTask is "not recommended for general use".
The desired behavior can be achieved using Intent flags FLAG_ACTIVITY_CLEAR_TOP and FLAG_ACTIVITY_SINGLE_TOP:
Intent intent=new Intent(ActivityC.this,ActivityA.class);
intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_ACTIVITY_SINGLE_TOP);
startActivity(intent);
finish();
Activity A will not be recreated and will receive the intent via onNewIntent().
Use SingleTask launch mode for Activity A.
New intent will be delivered to existing instance.

Android - Bring an activity to the front from application class

I am trying to bring an activity to the front. I found many questions similar to this but none of them actually works.
I always hold a reference to the current activity in a variable in application class. While the application is running in the background (after onPause fires), if any message arrives, I need to bring the same activity to the front and display the message. The only way I got it worked is..
Intent i = new Intent(mCurrentActivity, JoboffersActivity.class);
i.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
i.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
startActivity(i);
The issue I have got with this, is that it recreates the activity which I wanted to avoid. I tried singleInstance and singleTask both in the manifest. If I do not add FLAG_ACTIVITY_CLEAR_TOP, on back key press it takes me to the previous instance of the same activity. Even if I add sigleInstance it creates two instances of the same activity. If I do not add FLAG_ACTIVITY_NEW_TASK then it shows an error Calling startActivity() from outside of an Activity context requires the FLAG_ACTIVITY_NEW_TASK flag
Try to add another flag FLAG_ACTIVITY_SINGLE_TOP to your intent.
According to Android documentation, combination of this 2 flags:
i.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_ACTIVITY_SINGLE_TOP);
brings the current instance of Activity to the front.
http://developer.android.com/reference/android/content/Intent.html#FLAG_ACTIVITY_CLEAR_TOP

Removing an activity from the history stack

My app shows a signup activity the first time the user runs the app, looks like:
ActivitySplashScreen (welcome to game, sign up for an account?)
ActivitySplashScreenSignUp (great, fill in this info)
ActivityGameMain (main game screen)
so the activities launch each other in exactly that order, when the user clicks through a button on each screen.
When the user goes from activity #2 to #3, is it possible to wipe #1 and #2 off the history stack completely? I'd like it so that if the user is at #3, and hits the back button, they just go to the homescreen, instead of back to the splash screen.
I think I can accomplish this with tasks (ie. start a new task on #3) but wanted to see if there was simpler method,
Thanks
You can achieve this by setting the android:noHistory attribute to "true" in the relevant <activity> entries in your AndroidManifest.xml file. For example:
<activity
android:name=".AnyActivity"
android:noHistory="true" />
You can use forwarding to remove the previous activity from the activity stack while launching the next one. There's an example of this in the APIDemos, but basically all you're doing is calling finish() immediately after calling startActivity().
Yes, have a look at Intent.FLAG_ACTIVITY_NO_HISTORY.
This is likely not the ideal way to do it. If someone has a better way, I will be looking forward to implementing it. Here's how I accomplished this specific task with pre-version-11 sdk.
in each class you want to go away when it's clear time, you need to do this:
... interesting code stuff ...
Intent i = new Intent(MyActivityThatNeedsToGo.this, NextActivity.class);
startActivityForResult(i, 0);
}
#Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if (resultCode == R.string.unwind_stack_result_id) {
this.setResult(R.string.unwind_stack_result_id);
this.finish();
}
}
then the one that needs to set off the chain of pops from the stack needs to just call this when you want to initiate it:
NextActivity.this.setResult(R.string.unwind_stack_result_id);
NextActivity.this.finish();
Then the activities aren't on the stack!
Remember folks, that you can start an activity, and then begin cleaning up behind it, execution does not follow a single (the ui) thread.
One way that works pre API 11 is to start ActivityGameMain first, then in the onCreate of that Activity start your ActivitySplashScreen activity. The ActivityGameMain won't appear as you call startActivity too soon for the splash.
Then you can clear the stack when starting ActivityGameMain by setting these flags on the Intent:
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TOP);
You also must add this to ActivitySplashScreen:
#Override
public void onBackPressed() {
moveTaskToBack(true);
}
So that pressing back on that activity doesn't go back to your ActivityGameMain.
I assume you don't want the splash screen to be gone back to either, to achieve this I suggest setting it to noHistory in your AndroidManifest.xml. Then put the goBackPressed code in your ActivitySplashScreenSignUp class instead.
However I have found a few ways to break this. Start another app from a notification while ActivitySplashScreenSignUp is shown and the back history is not reset.
The only real way around this is in API 11:
intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK);
I use this way.
Intent i = new Intent(MyOldActivity.this, MyNewActivity.class);
i.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK)
startActivity(i);
I know I'm late on this (it's been two years since the question was asked) but I accomplished this by intercepting the back button press. Rather than checking for specific activities, I just look at the count and if it's less than 3 it simply sends the app to the back (pausing the app and returning the user to whatever was running before launch). I check for less than three because I only have one intro screen. Also, I check the count because my app allows the user to navigate back to the home screen through the menu, so this allows them to back up through other screens like normal if there are activities other than the intro screen on the stack.
//We want the home screen to behave like the bottom of the activity stack so we do not return to the initial screen
//unless the application has been killed. Users can toggle the session mode with a menu item at all other times.
#Override
public void onBackPressed() {
//Check the activity stack and see if it's more than two deep (initial screen and home screen)
//If it's more than two deep, then let the app proccess the press
ActivityManager am = (ActivityManager)this.getSystemService(Activity.ACTIVITY_SERVICE);
List<RunningTaskInfo> tasks = am.getRunningTasks(3); //3 because we have to give it something. This is an arbitrary number
int activityCount = tasks.get(0).numActivities;
if (activityCount < 3)
{
moveTaskToBack(true);
}
else
{
super.onBackPressed();
}
}
In the manifest you can add:
android:noHistory="true"
<activity
android:name=".ActivityName"
android:noHistory="true" />
You can also call
finish()
immediately after calling startActivity(..)
Just set noHistory="true" in Manifest file.
It makes activity being removed from the backstack.
It is crazy that no one has mentioned this elegant solution. This should be the accepted answer.
SplashActivity -> AuthActivity -> DashActivity
if (!sessionManager.isLoggedIn()) {
Intent intent = new Intent(context, AuthActivity.class);
intent.setFlags(Intent.FLAG_ACTIVITY_NO_HISTORY);
context.startActivity(intent);
finish();
} else {
Intent intent = new Intent(context, DashActivity.class);
context.startActivity(intent);
finish();
}
The key here is to use intent.setFlags(Intent.FLAG_ACTIVITY_NO_HISTORY); for the intermediary Activity. Once that middle link is broken, the DashActivity will the first and last in the stack.
android:noHistory="true" is a bad solution, as it causes problems when relying on the Activity as a callback e.g onActivityResult. This is the recommended solution and should be accepted.
It's too late but hope it helps. Most of the answers are not pointing into the right direction. There are two simple flags for such thing.
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK);
From Android docs:
public static final int FLAG_ACTIVITY_CLEAR_TASK
Added in API level 11
If set in an Intent passed to Context.startActivity(), this flag will cause any existing task that would be associated with the
activity to be cleared before the activity is started. That is, the
activity becomes the new root of an otherwise empty task, and any old
activities are finished. This can only be used in conjunction with
FLAG_ACTIVITY_NEW_TASK.
Just call this.finish() before startActivity(intent) like this-
Intent intent = new Intent(ActivityOne.this, ActivityTwo.class);
this.finish();
startActivity(intent);
Removing a activity from a History is done By setting the flag before the activity You Don't want
A->B->C->D
Suppose A,B,C and D are 4 Activities if you want to clear B and C then
set flag
intent.setFlags(Intent.FLAG_ACTIVITY_NO_HISTORY);
In the activity A and B
Here is the code bit
Intent intent = new Intent(this,Activity_B.class);
intent.setFlags(Intent.FLAG_ACTIVITY_NO_HISTORY);
startActivity(intent);
if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
super.finishAndRemoveTask();
}
else {
super.finish();
}
Here I have listed few ways to accomplish this task:
Go to the manifest.xml- and put android:noHistory="true", to remove the activity from the stack.
While switching from present activity to some other activity, in intent set flag as (Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK). It is demonstrated in the example below.
Intent intent = new Intent(CurrentActivity.this, HomeActivity.class);
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK |
Intent.FLAG_ACTIVITY_CLEAR_TASK)
startActivity(intent);here
Note :Putting the intent flags can cause blank screen for sometime (while switching activity).
Try this:
intent.addFlags(Intent.FLAG_ACTIVITY_LAUNCHED_FROM_HISTORY)
it is API Level 1, check the link.

Categories

Resources