How to Control Android back stack - android

Lets say I have
A->B->C->D->E
In android back stack. I want to be able to get back to one of the following:
A->B->C
A->B
A
How can I achieve this? Hopefully without forcing back button clicks.

Using the image and information from the official developers page on Android tasks and back stack you can see that of all other ways to launch an Activity you can ensure such behavior only using the FLAG_ACTIVITY_CLEAR_TOP in your Intent flags.
Your regular back button proceeds as:
But when you specify this flag, you get a behavior like you need, as given by an example at this source:
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.

Use FLAG_ACTIVITY_CLEAR_TOP flag.
Intent a = new Intent(this, A.class);
a.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
startActivity(a);

Actually , to go "up" to the activity of your choice, you should use the "up" navigation as used on the action bar:
/** used to handle the "up" button on the action bar, to go to the defined top activity as written on the manifest */
public static void goUpToTopActivity(final Activity currentActivity) {
final Intent intent = NavUtils.getParentActivityIntent(currentActivity);
intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_ACTIVITY_SINGLE_TOP);
NavUtils.navigateUpTo(currentActivity, intent);
}
in order to use it, you must set on the manifest to which activity this function should use (or you could of course set it yourself by changing the code) :
if you use actionBarSherlock, for each activity that you wish to let to go up, use:
<meta-data
android:name="android.support.PARENT_ACTIVITY"
android:value="com.your_app.activities.MainActivity" />
if you use the android framework (if your minSdk version is API 16 and above), use the "parentActivityName" attribute.

Suppose you are using Intent to move to another activity
Intent i = new Intent(A.this,B.class);
startActivity(i);
this code will take you to the 'B' Activity and when you press Back button it will again take you to the 'A' Activity . If you dont want to go back to activity 'A' you can use....
Intent i = new Intent(A.this,B.class);
i.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
i.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK);
startActivity(i);
For more information about Back Stack in Android Follow this link :
http://developer.android.com/guide/components/tasks-and-back-stack.html

Related

How to start a new Intent that will clear all other activities?

To lay it out as simply as possible. My user enters the app through Activity A. They "login" and then Activity B is started, and Activity A is finished using finish() so that the users can't get back to the login screen by pressing back from Activity B. Now in Activity B, they move to Activity C, and in activity C, I want them to start a new intent that will start activity A, but "kill"/"finish" all other activities. The only way I can think of doing this is using an Intent Flag. so far I've come up with:
Intent intent = new Intent(getActivity(), ActivityA.class);
intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_WHEN_TASK_RESET|Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED);
startActivity(intent);
But the code above doesn't work. I still see that my app had a savedInstanceState in Activity B. Hence something like CLEAR_TASK won't work for me case.
EDIT: Also, is there an easy way to tell have many "tasks" your app has opened currently?
Note: There seems to be other flags that may help, but they were added in API 11, and I need to support API 10.
Flag combos I've tried:
Doesn't work
intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_WHEN_TASK_RESET|Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED);
Doesn't work
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TOP);
You need to use IntentCompat. like
import android.support.v4.content.IntentCompat;
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK |IntentCompat.FLAG_ACTIVITY_CLEAR_TASK);
Check whether the below answer helps you:
http://www.hrupin.com/2011/10/how-to-finish-all-activities-in-your-android-application-through-simple-call

How to navigate to a particular activity?

I am having 3 activities. From the third activity, I need to come back to the 1st activity when a GUI button is clicked. I know I can click the "physical" back button 2 times to make this but that is not an option.
So, is there any way I can display the 1st activity, without creating a new instance? I can pass the 1st activity's instance to the third activity, no issue with that.
Use the FLAG_ACTIVITY_CLEAR_TOP in your intent.
From the documentation:
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.
To use:
Intent intent = new Intent(getBaseContext(), FirstActivity.class);
intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
startActivity(intent);
Intent intent = new Intent(src_ctxt, dest.class);
intent.addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP | Intent.FLAG_ACTIVITY_CLEAR_TOP);
src_ctxt.startActivity(intent);
This should do it
I think you need to make your activity B singleInstance that if it's already create you don't want to create again, that is launch mode of the activity can be defined in manifest android:launchMode that defines how the activity will be instanciated.
in your case use android:launchMode="singleInstance"
or
You can use flag Intent.FLAG_ACTIVITY_NEW_TASK. If the activity is already running it will bring that to front instead of creating new activity.

Flag similar to FLAG_ACTIVITY_CLEAR_TASK in API 8

My App has an Activity A which triggers B and B in turn triggers C.
Activity A is the launcher with the intent flag android:noHistory="true" in manifest file. This shows the splash screen. After 2 seconds it triggers B with the intent flag FLAG_ACTIVITY_NO_HISTORY. B triggers C normally without any intent flag. Now the Stack will have only the Activity C.
In Activity C, Whenever back is pressed It will trigger Activity B. Now the Stack should have the Activity B alone. It should not have any trace of other Activity.
I have used the following code in the Activity C. But the flag FLAG_ACTIVITY_NEW_TASK is available only from API 11. The app should be supporting the devices from the API 8. Kindly assist me with the correct intent flags to achieve the explained scenario
Code:
Intent dragDropIntent = new Intent("android.intent.action.DRAGDROP");
dragDropIntent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK);
dragDropIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
I agree that starting the Activity C without nohistory will help. But do t some technical constraints I don't want to do that. Thanks in Advance
you are looking for this:
Intent intent = new Intent(activity, activityClass);
ComponentName cn = intent.getComponent();
Intent mainIntent = IntentCompat.makeRestartActivityTask(cn);
activity.startActivity(mainIntent);
use android compatibillity lib from google - found in the sdk.
or use finish()
This flag is now available through the compatibility lib:
IntentCompat.FLAG_ACTIVITY_CLEAR_TASK
Hope this helps :)
If C is always goes back to B, then you should not use FLAG_ACTIVITY_NO_HISTORY. Then when the user backpress in C, C would be finished by the OS and the stack now only has B.

Android:Delete a activity in backstack

I have got 4 activity let it be A->B->C->D.In every A,B,C activity user need to enter data all data will sent to server in C activity if the user data is correct he will move on to D activity and all the activity A,B,C removed from stack.If the data is in correct i need give the user to reenter data i.e is on back press it has to move C->B->A.My question is How to remove A,B,C activity when user enter D activity.
Use FLAG_ACTIVITY_CLEAR_TOP this shall solve your problem
From the Android documentation:
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.
Use it like
Intent intent = new Intent(getApplicationContext(),
yourActivity.class);
intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
startActivity(intent);
and also, take a look at this question:
Activity with Flag FLAG_ACTIVITY_CLEAR_TOP (android)
Edit : I thought you want to move to your home activity from D and want to remove all activities from stack
Your stack would be like homeactivity , A , B , C , D
so i gave you this solution as this shall remove all activities in stack on top of your home activity.
If you want to clear the the stack while going to D, for that you can use FLAG_ACTIVITY_TASK_ON_HOME or FLAG_ACTIVITY_CLEAR_TASK
But both of these for api level 11.
The correct answer interesting for me also, but I can offer a solution:
For example you start activity A from O: O->A->B->C->D.
On activity O you can put in android manifest android:launchMode="singleTop"
Then, when data are ok, you can start activity O with flag "FLAG_ACTIVITY_CLEAR_TOP" - it remove from stack A,B,C and will be called method onNewIntent (Intent intent) http://developer.android.com/reference/android/app/Activity.html#onNewIntent(android.content.Intent) in O, where you can start activity D.
You can start activities with startActivityForResult, and call setResult from for example activity D, in C activity you can listen activity result, and related of this result finish activity or not, or call setResalt from C activity ...
When you want to move D activity there you need to check your
conditions and if your condition is satisfied then you need to enter
into your Next activity(i.e., D) .In that case you need to use the
following code..
Intent intent = new Intent(this,D.class);
intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK);
startActivity(intent);
Suppose In on backpress you need to use finish(). to move back i.e., C
-> B -> A.
Try this piece of code with some modifications:
Intent intent = new Intent(this, D.class);
intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP); // To clean up all activities
startActivity(intent);
Try looking for Activity's public method startActivity(Intent i) and finish() here
In usage wise, it should look like this.
Intent i = new Intent(MainActivity.this, MainActivity.class);
startActivity(i);
finish();
Hope this helps :D

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