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?
Related
I have an application with 3 layers. A, B, C.
A and B are fixed and C can be any one of the multiple activities.
Application normally works in A>B>C direction.
A calls B with startActivityForResult method. B calls C with startActivityForResult too and result of C is processed in B and passed back to A via onActivityResult methods on all layers.
It works fine but I somehow want the activity A to call C directly (where i have implemented a thread to do stuff in background) using
Intent i = new Intent("com.intentntfiltername.ACVITIY-C");
startActivity(i);
C then switches back to A by resuming it.
After this A would call B for result.
B would then call C using
intentName.setFlags(Intent.FLAG_ACTIVITY_REORDER_TO_FRONT);
startActivityForResult(intentName, requestCodeVariable);
that would not create new instance of Activity C but instead resume the old activity.
The problem is when I return to B after exiting C, onActivityResult is never called. It just resumes the B activity without processing any results from C.
i.e on Activity Result is not working when we try to call an already running activity for result.
Please tell me how to implement this. Or any other workaround only if its not possible for an already running activity.
when I finish an activity that was started for a result, I call for example
Intent intent = new Intent();
intent.putExtra("email", email);
act.setResult(RESULT_OK, intent);
act.finish();
where the returned value I needed is the email of course, and "act" is the activity that Ive created in the onCreate as
act = this;
My project has 4 activities and users from activity A go to B after that to C and D. I need to create a button in activity D to close program directly because if user has to close all activities ( D ->C -> B -> A-> close) it would be unfriendly.
Register a broadcast receiver in each of the activities, listening for the "close all action", when the button in the last activity is pressed, send that broadcast, so all the activities register will execute their "onReceive" method on the broadcastreceiver, and there all them will be finished as long as they are registered.
This will definitely do the trick, although to be honest is quiet a poor implementation, chances that you are doing something wrong in the navigation are high, maybe fragments or a tab would be better suited for what you are trying, in stead of creating such a stack of activities...
Hope this helps...
Regards!
I think onActivityResult could be the better option.You could finish the activity if required task is being completed otherwise just backtrack on previous activity
You should override onBackPressed() from each Activity and call finish().
Assume the first activity in your application is named ActivityMain. Presumably it will be the oldest one on the stack.
Create an intent to start ActivityMain using the flag FLAG_ACTIVITY_CLEAR_TOP. Set an extra in that intent to indicate this is an application exit, and call startActivity() with that intent. This will clear the stack and get you back to Activity main.
In ActivityMain call getIntent() then check for the exiting application Extra value. If it is set, call finish().
A not so elegant solution:
Instead of calling startActivity, call startActivityForResult, from A to D.
On Activity D, when your button is pressed, set any result (let's say Activity.RESULT_OK) and call finish().
On each Activity (from A to C), override the method onActivityResult to check for the result. If the result is Activity.RESULT_OK, then you set the same result and call finish() again.
If you want, instead of just setting the result, add an Intent with some flag to tell the previous Activities to finish themselves.
Simply do one thing . In your activities add an overriden method onPause
onPause(){
finish();
}
This will close all your activities once you press back from any activity.
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.
When I have two activities
Activity A, B;
// A stands for Login Screen
// B stands for Main Application Screen
Application starts with A, then user performs login and he will be pointed to B
When I launch B I add this flag to Intent Intent.FLAG_ACTIVITY_CLEAR_TOP but when I finish the B I expect it to be the last activity and to quit the application.
Instead of what I expected, A is brought to front, and user stills on Login Screen again.
Should I start A from B as startActivityForResult and use B as main activity of whole application ?
Or the flag is not working as it should be?
Don't bother with intent flags. When activity A starts activity B after a successful login, just have A call finish().
An alternative, slightly more involved, approach is to make B your main activity and in B's onCreate method, start activity A for a result, which should be some pass/fail flag. When Activity A finishes (either on a successful login, failure, or the user just quitting), activity B determines in onActivityResult whether to continue or to finish, based on the returned value. This works because, according to the docs:
As a special case, if you call startActivityForResult() with a requestCode >= 0 during the initial onCreate(Bundle savedInstanceState)/onResume() of your activity, then your window will not be displayed until a result is returned back from the started activity. This is to avoid visible flickering when redirecting to another activity.
Use finish method:
Intent lIntent = new Intent();
lIntent.setClass(this, MainActivity.class);
startActivity(lIntent);
finish();
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.