How to finish() two activities at the same time? - java

I am writing a math app for little kids to learn maths. It first prompts the user to select what kind of questions they want (MainActivity), and then it shows a bunch of questions (QuestionsActivity). After answering 10 questions, it tells you which question(s) did you answer correctly and which you didn't (ResultsActivity).
I know that Android puts all the activities on a stack. In my case, it would look like this:
ResultsActivity
QuestionsActivity
MainActivity
And when you call finish, an activity is popped from the stack. I want there to be a back to main menu button in the ResultsActivity to go back to the MainActivity. However, if I call finish in the ResultsActivity, the user would see QuestionsActivity! So how am I going to call finish on the both activities?

Two options:
Call finish() in QuestionsActivity after you make the call to start the ResultsActivity. This will remove it from the stack so that pressing back from ResultsActivity returns to MainActivity.
Use Intent.FLAG_ACTIVITY_CLEAR_TOP in the intent to go back to MainActivity. This will clear all activities that are on top of it.

You can clear your stack by simple starting your MainActivity again and clearing the stack with the following flags:
final Intent intent = new Intent(context, MainActivity.class);
intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK | Intent.FLAG_ACTIVITY_NEW_TASK);
startActivity(intent);

Related

How to stop transition animation on clear activity stack android?

A white screen blinks for few milliseconds when I simply go from login activity to Main activity with following clear back stack code.
Intent intent = new Intent(LoginActivity.this, HomeActivity.class);
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK);
startActivity(intent);
overridePendingTransition(0, 0);
If I just make the startActivity without Flags (or say without clear backstack)
overridePendingTransition(0, 0);
It doesn't blink with white screen.
But I have to clear back stack and start a new activity with NO transition animation. So it doesn't blink/appear in white screen for few milliseconds.
Looking forward to get a perfect answer soon. Cheers !
Try setting noHistory="true" for login activity in the manifest and start HomeActivity without any flags. This should solve your problem.
Don't use Intent.FLAG_ACTIVITY_NEW_TASK. If you want to clear the backstack (and assuming your login Activity is the only one in the stack), just finish the current Activity:
Intent intent = new Intent(LoginActivity.this, HomeActivity.class);
startActivity(intent);
overridePendingTransition(0, 0);
finish();
Intent.FLAG_ACTIVITY_NEW_TASK is likely the cause of the flash since it requires you to create a whole new "task" (which is a collection of Activities with a given history) rather than just reusing the current one. It's almost like navigating to another app at that point.
As I have mentioned in the question that startActivity without using flags makes no blink and showing white screen.
So I choose that.
Now the problem is to clear the stack of 1st Login activity when I am into Main Activity.
I resolved it by setting the context of Login activity into Application class using setter and getter method.
And Whenever You reached to Main Activity. It will check whether you have the context in Application class by getter method.
If it's a yes and is a login activity then make the context.finish which will clear the back-stack by removing the login activity from Main Activity. And set null value to setter in Application class.
Feel free to share any concern regarding this. Thank you.

launchMode stops extra from transfer in intent

I have been trying to figure out why my Intent would not transfer string data from one activity to another activity? I seems I had set launchMode = singleTask in the manifest folder and when I changed launchMode to standard the Intent code worked as expected.
The MainActivity is the first activity in the stack I am guessing that I made the setting a number of months ago to try and prevent the user from using the back button to navigate back to the password log in page. (MainActivity)
I kind of get the Back Stack idea but WHY would this setting inhibit the intent from transferring data. my test for transfer was a System.out.println statement?
Suppose you have activities A and B. A is the one with android:launchMode="singleTask". A starts B. B then starts A, causing the existing instance of A to return to the foreground.
In that case, A is called with onNewIntent(), and that Intent will have the extras from B.
onCreate() is only called when an activity is created.

Any consequences of startActivity() after having already started the activity?

Let's say I have Activity A and Activity B.
In A, I have a button which when clicked runs the following code
startActivity(new Intent(this, ActivityB.class));
In B, I have a button which when clicked, runs the following code
startActivity(new Intent(this, ActivityA.class));
So when the app is started and the user does the following:
Clicks on button in Activity A (he goes to Activity B)
Clicks on button in Activity B (he comes back to Activity A)
Again clicks on button in Activity A (goes to Activity B again)
In this case, do the Activities A and B hog the memory since they get started each time or is Android smart enough to know that an activity has already started and simply needs to be put on top of the stack?
So in other words, if memory does indeed gets clogged up, is there something like:
if(activity has already started)
{
doNotStartActivityButSimplyPutItAtTop();
}
else
{
startActivity(new Intent.....);
}
yes, your assumption is right android is capable of managing these activities and they are maintains proper stack for it.
if you are having only two activities you can use singletop launcher mode so that only only two activities remain in stack.
The android system may release the resources from previous activity in the stack. To avoid losing the current state of the activity you may have to save it and then restore when the activity is recreated. See Recreating an Activity.

Android: Clearing only second activity in the stack (or clearing specific activity)

In my app there are three activities.
A can open B
B can open C, or return to A, or return to C (if opened from C)
C can open B, or return to A
I have implemented this using various RESULT_CODEs and onActivityResults. However, the stack becomes too large after prolonged use of the app!
I need to clear activities from the stack. Looking at my app's structure, the best clearing method revolves around clearing whatever is the second activity on the stack (assuming A is always the first/bottom activity on the stack). I made a quick painting to make it easier to understand:
Once B is added onto ABC, the previous B (second activity in the stack) is removed. Once C is added onto ACB, the previous C (second activity in the stack) is removed.
I can think of two methods that do what I describe:
clear whatever is the second activity in the stack
remove any activities in the stack that are the same as the one that I am creating (C creates B, so the other B needs to be cleared)
However, I have not found a way to implement this in code. I have tried using Intent.FLAG_ACTIVITY_CLEAR_TOP, but that clears everything in the stack except for A, before adding the new activity at the top.
So my question: How can I implement method 1 or method 2? (Does not matter which one)
Here is an example of me clearing all in the stack but A:
Intent newActivity = new Intent(this, B.class);
newActivity.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
startActivityForResult(newActivity, MY_REQUEST_CODE);
I am also open to alternative methods. Maybe using FLAG_ACTIVITY_NO_HISTORY somehow?
So it seems like you would like to keep one instance of B activity and C activity. This can be done with adding an XML attribute in your Manifest.xml
<activity android:name="B" android:launchMode="singleTask" </activity>
"singleTask" - 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.
Refer to here for more information.
I have occurred the same problem , to kill some specific activity .. my solution was to implement StackActivityManager used for managing activity :
Each activity was saved on static list which contains all activity of my application
The saving of activity was done the mother class base activity
Each activity have a static and unique tag used later to indicate which activity will be remove from the stack of activity
The launch mode is singleTask to avoid duplicate activity in the stack of activity.
try to do method:
Intent intent = new Intent(Activity1.this, Activity2.class);
startActivity(intent);
//The finish(); method, destroy the current activity.
finish();
after call the next activity, then the current activity destroys.
I hope that it works. :)
remove this line
newActivity.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
Try adding in your code-
Intent newActivity = new Intent(this, B.class);
newActivity.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
newActivity.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK);
startActivityForResult(newActivity, MY_REQUEST_CODE);
Note: What Cory Charlton wrote in his comment about Fragments is probably the best solution for anyone having similar problems. I recommend trying that route instead of my own solution. The only reason I went with my own solution is because I needed a quick solution, and had not the time to learn how to implement Fragments before a deadline.
I ended up solving the problem by having the A activity always start the C activity, instead of the B activity. The B activity no longer creates a C activity, it instead finishes in order to go back to C.
This way the stack never gets bigger than 3.
And to provide some code, I had to add this before finishing in the B activity, since it now no longer is passing an object, but is returning it:
setResult(RESULT_OK, getIntent().putExtra(KEY_MY_OBJECT, myObject));

how to make the appliction exit when pressing back button in the main activity?

In my application when i click the back button it passes through all the activities that i open them previously , i used the public void onBackPressed() method to make the back button back to the activity that i want as follow
public void onBackPressed()
{
startActivity(new Intent("com.MyDiet.Main"));
Tracker.this.finish();
}
is that true and safe way to code the back button ? how i can prevent the application from passing through all the previous opened activities when the back button is pressed ? and how i can make the application exit when i click the back button in the main activity?
In your application, and in ALL android applications, unless it's critical not to pass through unneeded steps (such as login if you're already logged in), it's VERY important not to override Android standard behaviour. Users normally complain about Android apps not having a common behaviour or style guideline.
Anyway, yeah, you can just override onBackPressed on all your activities and do whatever you want. But just don't.
This approach isn't good, because you're polluting the activity stack of your application
Example:
current stack: MainAct -> Act2 -> Act3 (we're in activity 3)
With your code above, when you press back, the stack now looks as follows:
MainAct -> Act2 -> MainAct
Because you ended Act3 and launched a NEW main activity, which may be not what you wanted.
To achieve what you want (Get back to main when the current activity is over) you need to work on the intermediate activities: In the example above, when from Act2 you call startActivity("Act3"), you should call "this.finish()". Therefore you don't have to override "onBackPressed()" of activity 3: simply the default value will terminate Act3 and the next activity in the stack will be MainAct
MainAct -> A2 (A2 launches A3 and then calls this.finish())
MainAct -> A3 (user now press back)
MainAct (the mainactivity is now on top)
To summarize, you don't have to override onBackPressed, you just have to correctly manage the lifecycle of the activity between the main one and the current one.
Generally speaking it's not recommended to make things work like user doesn't expect and that is considered as very bad practice. That's why it is not good to start activity from overriden onBackPressed().
When user press back by default activity will finish and one from back stack will be displayed. You as developer will (by writing code) decide which one is that. You can do it this way but later (or for somebody else) it will be a bit messy and difficult to find this unusual place for code which is starting other activity.
So..It would be useful to read about activity lifecycle and back stack to get impression how it works and understand terminology better.
If you want one of your activity not to stay on back stack you can add in manifest file file android:noHistory="true" for that activity.
Same thing you can achieve from code by adding appropriate flag to intent when you start activity: Intent.FLAG_ACTIVITY_NO_HISTORY
When user "go away" from ActivityOne (started using intent or defined in manifest like described), to new ActivityTwo and then press back, it will not go to ActivityOne because it will not be on back stack. Using this you can precisely control navigation through your activities.
More flags are available for use, but I guess this is what you wanted to achieve.
Hope you will find my answer useful. Cheers..
You can use a lot of tricks to exit your complet application for my part i use this start a intent and then from the androidmanifest i choose the category to home and than close the current activity such would be your mainactivity !
public void onBackPressed() {
Intent intent = new Intent(Intent.ACTION_MAIN);
intent.addCategory(Intent.CATEGORY_HOME);
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
startActivity(intent);
finish();
}

Categories

Resources