I have an activity A which starts a new activity B with startActivityForResult.
Activity B is restarted several times with FLAG_ACTIVITY_CLEAR_TOP, so when the user clicks on back, B puts on data with setResult() and comes back to Activity A. However, the data is missing. onActivityResult in A is invoked with intent to null and resultCode by default.
I know that, in fact, is the right behaviour since FLAG_ACTIVITY_CLEAR_TOP discards previous activities, but I wonder if there is some workaround to achieve this (apart from obvious options like avoiding restarting B)
Add both FLAG_ACTIVITY_CLEAR_TOP and FLAG_ACTIVITY_SINGLE_TOP to your launch intents when you restart Activity B.
activityBIntent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_ACTIVITY_SINGLE_TOP);
Also relaunching Activity B will call onNewIntent(Intent), however getIntent() will still deliver the older (original) intent.
Note that getIntent() still returns the original Intent. You can
use setIntent(Intent) to update it to this new Intent.
Related
I'm just learning Android programming. The way I understand it is that the services work like a stack, Is there a way for a activity to return to the first activity that started the app, instead of just the previous one.
Example, say I have 4 activities, a,b,c,d. Is there a way for activity d to have a button that would bring up activity a?? Instead of activity d going to c, and c going back to b???
You can start again activity a, but using a flag in your intent:
FLAG_ACTIVITY_REORDER_TO_FRONT
From android docs:
If set in an Intent passed to Context.startActivity(), this flag will cause the launched activity to be brought to the front of its task's history stack if it is already running.
Using this, you'll reuse the instance of activity a already running, instead of starting a new one. Note that doing this, the instances of activities b, c and d will remain in the back stack (now after activity a).
Otherwise, if you want to finish this activities (and remove them from the back stack) you can start activity a (from d) with this other flag:
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.
EDIT: this is a good resource to read, if you haven't did it yet:
Tasks and Back Stack.
Yes, you can do that. You simply code an intent for activity a to the button.
Use the command
finish():
You will be reverted to the main page
or else write an intent pointing to a
You can send information to different Activities via Intents.
Intent myIntent = new Intent(this, AvitivityName.class);
startActivity(myIntent);
Don't forget to add your Activities in AndroidManifest.xml.
Here's some tutorial on Android Intents:
how to use Android intents.
how to switch to another activity with a button click.
I have an Android application that contains two Activities.
Activity A has a button that launches Activity B using Context.startActivity(Intent intent).
There is also a Notification that opens Activity in the same way.
If I start B from this notification and press back button - it just closes B and does not shows A like I go there with normal case.
Is it possible to force B to bo back to A if started from notification without history stack ?
Solution
As stefan and Paul Lammertsma mentioned, the best way is to start A from notification and in A create new intent with B - but not in onCreate() !
I dig this a bit and found that if I set in AndroidManifest a new property for A activity:
android:launchMode="singleTask"
there will be in A activity called
onNewIntent(Intent intent)
And there we should checl if Intent containst extra value passed from notification - and if so, then we call new B intent.
Thank you both and good luck with it for next devs ;-)
I would suggest having the notification call Activity A (instead of B directly) with some flag in its extras bundle. In A's onCreate(), check for the flag, and immediately launch Activity B. This will ensure that pressing back on B will return to A.
An easy way to achieve this would be to actually start Activity A from your Notification with a flag to call Activity B instantly.
So you just have to put an extra to your intent you are starting in your Notification and you have to check in Activity A if this extra exists and if it exists then you start Activity B.
Update: another way, but in my opinion not so good, would be to override the onPause() method of your Activity B and call Activity A there.
Maybe not the prettiest solution, but nevertheless a quick one;
add a boolean extra to the intent launching B, "launchedFromNotification" or something like that.
In activity Bs onCreate() you store that boolean value for later use.
In activity Bs onBackPressed() you can check the value of your boolean and if true, launch activity A before calling finish();
A prettier solution may be to launch activity A from the notification, with an extra telling it to directly launch activity B.
I want to finish my app calling the first activity with Intent.FLAG_ACTIVITY_CLEAR_TOP and finishing it. However, when it finishes, the app restarts automatically, and goes directly to Activity 2.
Why? Isn't the stack of activity supposed to be empty after finishing an activity called with Intent.FLAG_ACTIVITY_CLEAR_TOP?
My stack is Activity2>(more activities)>Activity1.
In Activity2
Intent exit_intent=new Intent(context, Activity1.class);
exit_intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
exit_intent.putExtra("EXIT", true);
context.startActivity(exit_intent);
In Activity1
if (getIntent().getBooleanExtra("EXIT", false)) {
finish();
}
From the javadoc:
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.
CLEAR_TOP will wipe out all Activities ABOVE Activity1: if Activity2 is below Activity1 then once Activity1 finishes you will see Activity2.
Are you sure finish() is being called properly in Activity1? I'm getting the feeling it's not, because:
I'm not sure where that if statement goes inside your Activity. It should be in onNewIntent.
If you are making that if statement inside the onNewIntent method, it's still wrong. The docs specify that getIntent() will always return the original intent that started the Activity, unless you call setIntent().
To conclude, maybe something else is getting called in your Activity1 (can't tell without the full code) that starts Activity2 instead of finishing.
If what I described is not the case, and your activity stack indeed looks like Activity2 > Activity1 like the others have described yes, it will not work. Just call finish() in Activity2?
According to the docs:
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.
So it doesn't clear the entire activity stack, only any other activities that were on top of an old instance of the activity being launched.
You have it right but are you catching the intent inside onNewIntent method of your first activity? also activity 2 should be launched after activity 1 in order for this to work.
From Intent doc:
public static final int FLAG_ACTIVITY_CLEAR_TOP
If it has declared its launch mode to be "multiple" (the default) and you have not set FLAG_ACTIVITY_SINGLE_TOP in the same intent, then it will be finished and re-created.
I have the following scenario (note that activity A has launchMode="singleTop"):
Activity A calls startActivityForResult() on activity B;
Activity B calls startActivity() on C, after which setResult(RESULT_OK) and finish(); at this point, onActivityResult() in A is NOT called.
Activity C calls startActivity() on A using FLAG_ACTIVITY_CLEAR_TOP and finish();
This is where my problem occurs. At this point, A's onActivityResult() is called with the right requestCode, but something else than RESULT_OK as the resultCode. I was expecting it to receive RESULT_OK because I have set it in B (which was started for result).
Why am I getting something other than RESULT_OK?
Read this doc:
http://developer.android.com/reference/android/content/Intent.html#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.
Passing clear top flag will finish all activities in the stack. So what you'll get in onActivityResult is probably a "notification" that the activity for which you want the result was canceled. (aka RESULT_CANCELED = 0x00)
UPDATE
When I use startActivityForResult, after setting the result, I always finish my activity and let the caller come to action.
You are doing something less common: you set the result, finish your activity but you also start another one. I don't know is the expected behavior in this situation. Can't you change the interaction between the activities?
You could try to call finish() first and then start the new activity (do this in activities B and C). Anyway, I also don't know what should happen when you do this. I recommend you the first approach (changing the interaction so you don't return a result and create a new activity at the same time).
Perhaps you could chain two startActivityForResult or your activity B could send a new intent to A instead of returning its result?
In my application you can navigate through several Activities until the Activity stack is quite deep.
We'd like a button on every Activity that will take you straight back to the main menu - i.e. pop all Activities from the stack except the first one.
I've put the button in a View that I can easily put on every Activity in the application, but I can't figure out how to close several Activities in one fell swoop.
(If possible, it would be good if the View could work out how many Activities to close by itself - i.e. detect how deep on the stack its own Activity is.)
Have a look at the intent flag FLAG_ACTIVITY_CLEAR_TOP which says it brings the targeted activity to the top of the stack, removing everything else that might have been above it. So use that button you can add to all your activities to launch an intent which targets your main menu, with that flag set.
From the 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.
The currently running instance of
activity B in the above example will
either receive the new intent you are
starting here in its onNewIntent()
method, or be itself finished and
restarted with the new intent. If it
has declared its launch mode to be
"multiple" (the default) and you have
not set FLAG_ACTIVITY_SINGLE_TOP in
the same intent, then it will be
finished and re-created; for all other
launch modes or if
FLAG_ACTIVITY_SINGLE_TOP is set then
this Intent will be delivered to the
current instance's onNewIntent().
This launch mode can also be used to
good effect in conjunction with
FLAG_ACTIVITY_NEW_TASK: if used to
start the root activity of a task, it
will bring any currently running
instance of that task to the
foreground, and then clear it to its
root state. This is especially useful,
for example, when launching an
activity from the notification
manager.
You could declare that first activity android:launchMode="singleTask" (more) and then just start it with an Intent.
EDIT: My suggestion is based on the assumption that you want to have a single instance of the Activity to return to. Otherwise it's incorrect.