Clear activity stack before launching another activity - android

Hi there (my first question here ;-)
There might be similar questions but none of them seem to answer my question or gives me a real solution...
Problem
A (root) starts B. B can start other activities. A decides to dismiss the stack (network connection loss) and start C. This seems to be a drastic decision but the user would expect that and that really makes sense in this case...
Question
How to do that? I would expect using a certain flag or just call something like dismissStack. But I can't find the right solution (see research below).
Research
I read a lot of documentation but the available flags don't match my needs (or I didn't understand it right). Other answers out there tell me to remember the started activities (e.g. in an array) and finish them when needed. But this seems dirty to me and somehow I can't accept that to be the right solution. There must be something cleaner I hope?!
(Storing the stack seems even wrong to me. Your app can be killed by the system, so your static data, but your history will be loaded again on startup. So you would have to persist your saved stack. This gets even dirtier...)
Update
My code and what I have tried (abstracted):
// in A
startActivityForResult(new Intent(this, B.class), REQUEST_B);
// network fail in A
// setting any flags on C has no influence
startActivityForResult(new Intent(this, C.class), REQUEST_C);
(FLAG_ACTIVITY_CLEAR_TOP is no solution, please read the documentation...)
I press Back on C and B still pops up and is so still there...
I can remove the activity by calling finishActivity(REQUEST_B). But when B started another activity D it will still pop up if I hit Back on C later. B is gone but D is still there...
I'm sure there is something I didn't understand yet or just missed. Can someone give me a hint or approve my research if it has to be really that way...

I think you are looking for the FLAG_ACTIVITY_CLEAR_TOP flag to be used with your intents.
From the documentation at the link above, an example is provided:
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.
You can see more about Tasks and the Backstack in Android at this link in the Android Dev Docs

That's what I got so far and it works pretty good:
Use startActivityForResult. Create a dummy request code if you actually don't need to wait for a result. Then do this in onDestroy of every activity.
if (isFinishing()) {
finishActivity(REQUEST_CODE);
}
For example: You have A, B, C, D on the stack, call finishActivity(REQUEST_B) from A, this will chain the onDestroy calls so B kills C and C kills D.
That's the best solution I can think of. Other solutions out there are messing with the activity lifecycle and/or are error prone.
I still hope there's a cleaner way...

You can use both the flags for new task and clear task to clear all previous activities from the stack
i.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK);

Related

Detail Explanation of LaunchMode in Android

I want to learn the concept and idea for using launchMode in Android. When to use which mode and a little detail about each of them.
Because I am facing an issue in Animation Transition between Activity. As i go from Activity A to B. Amimation shows smoothly but when i go back to Activity A by calling finish() Animation doesn't look as it goes from B to A. I googled it and some answer says to add singleInstance or singleTask to Activity in manifest. And some say to add flag Activity_reorder_to_front and so many other answer. Now I don't want anyone to solve my issue. I just want to learn these concept to get my job done myself.
and also suggest me which one is preferable for my current situation. I must call finish and i don't want to create a new Instance of Activity A.

(Activity recreation): what to do with a backstack built on invalidated data?

What to do when:
1. The app uses a complex structure of Activities and Fragments
2. I return to a backgrounded application that has been (partially or not) destroyed in the meantime
3. It returns me to the last screen, which lies deep in the workflow
4. I need it to return to the first screen to reinitialize things (because it's complex and requires user interaction)
Just to be clear:
I am asking how to deal with the existing stack(s) of Activities and Fragments upon encountering this situation.
- action to take: launch an Intent? Just finish? Do something to held substructures and then finish?
- when to perform it - immediately in both Activity.onCreate and Fragment's empty constructor? Or are Activities sufficient?
- How best to detect it: all I've come up with so far is: binding to a Service that holds the necessary data/connection, and then asking if it's been initialized. But the binding finishes AFTER onResume.
I am not asking about anything UI-related.
I am not asking for a solution that will only work for one specific application, so don't ask for code.
If you see this question as vague, here is a one-sentence version: "How to dismiss the stack and return to the first screen?"
For details (as much, at least, as are relevant), see https://stackoverflow.com/questions/14650342.
If you recognize that your application is in an inconsistent state and you need to start over, the easiest way is to relaunch your root activity like this:
Intent intent = new Intent(this, MyRootActivity.class);
intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
startActivity(intent);
finish();
This will clear all activities from the task and restart the root activity.
I would suggest doing this in onCreate() of activities.
when app is in the background and os wants to free some memory. whole PID is killed, which kills ALL activities. Docs are misleading about this behaviour. See this post
Android app out of memory issues - tried everything and still at a loss
where hackbod (Android platform developer) kind of confirms it.
When you have mulitple activities A,B,C and when your app is killed and you want to bring it back.
onCreate(not null) of most top activity will be called. Its worth noticing that when this scenario happens and you do something like
onCreate(not null){
startActivity(new intent)
finish;
two things will happen :
startActivity will launch new activity
finish will close current activity BUT it will bring back the previous activity (from killed pid) with its onCreate(not null) which simply was next activity in the activity stack.
This might cause multiple activity instances problems.
I had a similar problem some time ago, ended up with ugly hack but it worked :
to reinit whole app, I added something like
onCreate(not null){
if(launcher activity == null){
finish();
return;
in all activities.
Depending on what you want to achieve use flags as others have suggested.
Hope that gives you some hints.
If your goal is to dismiss all the activities and get back to your home/main activity then you can simply use:
Intent intent = new Intent(getApplicationContext(), Home.class);
intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
startActivity(intent);
This will clear all the activities on top of home and return you to the home screen.

Starting an Activity from Notification destroys Parent Activities

I have an app with 4 activities int the sequence say A->B->C->D and a service S that is started by A when the app is started. Now on a particular condition this service triggers a notification which again should start activity C withing my app and with the arguments that C usually needs from B. Also to function properly, C needs to use a static variable from the activity A. That was the setup.
Now what happens is when the notification is triggered from the service S and I click on it, activities A and B are automatically destroyed resulting in a force close(Since my activity C depends on a static variable in A). Why does this happen. I have used a TaskStackBuilder to place C's parent activity(i.e B) onto the stack so that normal back behavior takes me back to activity B.
Can anyone tell me the reason of this behavior. I do not want to run my Activity C as an interdependent task. I want it to be the same instance as that already in the app.
Please help me understand the problem here.
Activity should be independent. It is dangerous that activity C needs to use a static variable from the activity A. Although you create activities in order like A->B->C->D, Android may destroy A/B/C/D when your app is in background, and when user returns to your app, only activity D is recreated.
I encountered the same problem as you once, Starting an Activity from Notification destroys Parent Acitivities. This is because I used TaskStackBuilder. And even after I stop to use TaskStackBuilder, the problem remains. Only after I uninstall the app, it works as expected.
Check the comments for https://stackoverflow.com/a/28268331/1198666
This is happening because the Activity Lifecycle behaves differenty from ICS onwards. This fact answers this question, however I am yet to find out why this is happening. If someone wants to see the code and verify this behavior for themselves, HERE

Different behaviors on back key pressed

I've got four activities which the application cycles through. The first one fetches huge amount of data, so I don't wish to do that more than once. Thing is that if user presses back key on last activity, I want to return to the first one without reloading the activity. I'm currently thinking startActivityForResult methods and finish the two previous ones, but there may be a better solution?
Scenario:
Hasslarn,
The first thing that you must understand is that you have very little choice as to whether an Activity will be reloaded or not. That is determined by the system (largely). With that said, there are a number of things you can do to limit the system's desire to kill the Activity. Additionally, you may use a number of tools at your disposal to limit the impact of such a possible closure
Finish every child Activity as it becomes unimportant. This will free resources lowering the need to get rid of unused Activities (even temporarily).
Find a simple, but clever way to limit loads.
Based on the information provided, your proposed solution is a viable way to accomplish both. However, I would ask "Is Activity B required to be active while Activity C is open?" If not, you may want to do the following:
startActivityForResult(Activity B)
When Activity B is done, send result back to Activity A and startActivityForResult(Activity C)
Finally, when Activity C is done, you may startActivityForResult(Activity D) and back will work with no effort and you won't have to close the other activities.
Furthermore, if you press Back on Activity C, you can supply a cancelled result to Activity A forcing a restart of Activity B if you so desire. Depending on the required processing for Activity B, this may not be any hassle at all for your app.
Regardless of how you approach this, I recommend finding a way to cache this data such that onResume(), you may reload quickly if needed. This is because there is NO way to ensure that your original Activity will not be released to make way for the others.
Hope this helps,
FuzzicalLogic
Try using this:
Intent a = new Intent(this,A.class);
a.addFlags(Intent.FLAG_ACTIVITY_REORDER_TO_FRONT);
startActivity(a);
return true;
Activity A will get reordered to front, without creating a new instance. If you want to pass extras through intent , you can get the intent extras in onNewIntent(intent) in Activity A.

How do I 'navigate' to an activity that's already running?

Newbie question... So I have two activities, Cherry and Apple, and each one has a button on it to go to the other one. So back and forth.
In class "Cherry" I say this:
intent = new Intent(Cherry.this, Apple.class)
startActivity(intent);
Meaning that it should go to the Apple. There's similar code in the Apple activity.
What I think I am seeing is, is that each time when I startActivity Apple for example, it's starting a new instance of it instead of just reactivating Apple. I've scoured the doc and can't find the flag or other call that would do what I want.
Any tips would be appreciated!
-- Pito
What about FLAG_ACTIVITY_REORDER_TO_FRONT?
FLAG_ACTIVITY_CLEAR_TOP is also quite useful, finishing activities on the back stack until the target activity is reached.
To be clear, your activity may be restarted even if using the flags above. This would happen if your activity were destroyed in an attempt to free memory. In other words, you still need to make sure your activity can handle being restarted, taking the proper precautions in onPause and onSaveInstanceState.
Intent.FLAG_ACTIVITY_REORDER_TO_FRONT will bring the launched activity back to front if it's already running as given here. You will have to handle the back button yourself so as not to finish the current activity.

Categories

Resources