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.
Related
My application is launched using a tag, and based on the information contained in tag, it further proceeds. Now my app can also be started by using touching icon, and later it asks user to touch the tag. Small flow would be as below.
So MainActivity may contains tag data(if started from TagProcessorActivity), or may not contain data (if started from icon launch). Data is passed as intent extra value from TagProcessorActivity to IconLaunchActivity then to MainActivity. After main activity, app operation proceeds. When I leave the main activity, all my previous activities gets finish. I have checked onDestroy() is called for each activity. Now if I logout after MainActivity, (Logout simply a feature that closes all existing activity), and relaunch my application from recent app, my tag details still appears in MainActivity, which I dont know why.
To make is more clear my questions are:
1) Why activity which was destroyed still contains the information from previous launch.
2) I know about removeExtra() method, but is there some better options to tackle this problem.
3) and none the less, is there some thing wrong in my code or android is keeping that instance of intent extra?
PS: Not clear which piece of code to post, so if required feel free to ask for code.
Applications never exit in Android. onDestroy only destroys the activity, not any static variables left in the app. These will keep their value the next time an Activity is launched. This can be combined with some other features (like launching from the recent tasks menu causing you to launch the same intent) and this is the behavior you will get. The answer I always used was to detect this case (by checking the intent, there's a field that says if this is a restart or fresh), and ignoring the intent extras if so.
A finished task launched from Recents (as opposed to home screen launcher icon) will receive the old Intent, including its Extras, Data, etc. There is a way to know that it was launched from Recents so you can handle the Intent appropriately.
protected boolean wasLaunchedFromRecents() {
return (getIntent().getFlags() & Intent.FLAG_ACTIVITY_LAUNCHED_FROM_HISTORY) == Intent.FLAG_ACTIVITY_LAUNCHED_FROM_HISTORY;
}
In my humble opinion, that flag is poorly named (other flags referencing the Recents list actually use that word, e.g. FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS, FLAG_ACTIVITY_RETAIN_IN_RECENTS) and the documentation was never updated to reflect the fact that many popular Android devices have a dedicated button for Recents:
This flag is not normally set by application code, but set for you by the system if this activity is being launched from history (longpress home key).
I have 2 activities. Main Activity A & Activity B
I do not want Activity A to destroy. I am starting Activity B in a new task.
public static void startActivity(Class<?> startClass) {
Intent intent = new Intent(Constants.getActivity(), startClass);
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
Constants.getActivity().startActivity(intent);
}`
Constants.getActivity() returns the Context on current activity
startClass is the either activity "A" or activity "B"
Thing is they create/destroy the activities and they leak. Am I doing it wrong? How can I start activity "B" from activity "A" and vice versa keep them both in background when I dont need them.
First of all, what are you trying to do? You should always separate things you want to do in the background from your UI. Think of your Activities are simply a container to show the UI, everything else can be stored and restored from persistent storage or savedinstance bundles.
It is very crucial that you understand the difference between Activity lifecycle and Service lifecycle here.
I'm going to refer to my answer from another question here:
Your app will be in the background, onResume and onPause will both be called, provided that the OS have enough memory to keep the new app and all the old apps.
If you have a long running process that you need while the user not looking at it, use a service.
If you need the user to return the app in the same state, you need to do the work in onResume and onPause to save the state information and initialize your UI again when the user comes back. If you are really worried that it can get killed (well, it shouldn't lose the bundle I think), you can store them in SharePreferences for your app.
If you want to know when the app returns from that specific share intent, use startActivityForResult
You cannot keep an activity "alive" as you said. When an activity is paused, Android system is always able to claim its memory and unload it, at any time.
But if you want to switch from A to B, then maybe A and B can be different views inside a single activity. Maybe you'll want to have a look at http://developer.android.com/reference/android/widget/ViewFlipper.html
When you use tasks, cleanup is very important. You need to cleanup all tasks in the activity. readthis
If the activity does not have a lot of crazy initialization, just use finish and onCreates. Else be aware that onResume will be called often as you switch between activity's. Cleanup will be crucial here. If you dont cleanup, its possible one of your activities (with dead object reference from the other cleaned up activity) may come back up from the activity stack and throw exceptions. Its very difficult to debug this kinda exception.
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.
I have a lot of Activities on top of each other in my application and I want to close all these activities in one click. Can we do that.
And another thing is I want my application to start fresh each time(dont want to run in background). How can I do that?
There is no such thing as "closing" application or activities on Android. Please read: Is quitting an application frowned upon?
If you have a lot of instances of the same Activity class, then you might review your activity stack and task design.
I believe you can do it with this:
#Override
public void onClick(View v)
{
Context context = v.getContext();
Intent intent = new Intent(context, Dashboard.class);
intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);// This flag ensures all activities on top of the Dashboard are cleared.
context.startActivity(intent);
}
In this case, my Dashboard.class is the main opening activity of my application so its a way to take a user back to the start.
Not 100% sure there is a single android method that will close all of your related Activities but I think it might be possible if you use Broadcasts and broadcast receivers.
For example, if one of your Activities is currently 'on top' and the user closes it, the 'on top activity' could broadcast a close intent. all your other activities would have receivers listening for this activity and could then call finish() to end.
As for starting a fresh on each time this might be complicated. You'd have to look at overriding the 'home' and back buttons maybe but I highly advise against this. This is also complicated by the fact you want to achieve the above as well I think.
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.