In my App, Activity1 launches Activity2 with "startActivityForResult()".
When Activity2 is done, the following code is called:
Activity2.java
private void finishActivity(final boolean accepted)
{
Intent returnIntent = new Intent();
setResult(accepted ? RESULT_OK : RESULT_CANCELED, returnIntent);
finish();
}
Activity1 receives this callback, and if the result is not RESULT_OK, it also finishes.
Activity1.java
#Override
protected void onActivityResult(int requestCode, int resultCode, Intent data)
{
super.onActivityResult(requestCode, resultCode, data);
if (requestCode == Globals.REQUEST_CODE_TOS)
{
if (resultCode != RESULT_OK)
finish();
}
}
After Activity1 finishes the app closes, as expected.
THE PROBLEM --
However, after my app closes, instead of going to the home screen, a previous application on the stack briefly launches forward, then closes also! Then I get to the home screen.
In the Android bug tracker, I see a similar bug listed for the case when the back button is pressed, which I believe is the same as calling finish():
https://code.google.com/p/android/issues/detail?id=71067
I'm seeing this on a Nexus 5, running 4.4.4.
Is this just a bug? Or are there any workarounds for the behavior?
EDIT --
To clarify the behavior I desire:
In Google Maps, if you decline the TOS popup, the app closes and you go directly to the home screen. There is no awkward flash to some previously opened app.
This is decidedly the same issue as the one you linked in your question (I've been following it for months, as I own a Nexus 5 myself). It was actually fixed in the AOSP, but that particular fix doesn't seem to have found its way into the N5 yet. I've got my fingers crossed for a fix in Lollipop, but we'll see when that rolls out.
As for a workaround, I don't think any exists at the moment, although if I'm wrong on that I would love to know - I work on an app myself which does something similar (manually calls finish() the bottom-most activity in the stack when closed via the back button).
Might be the empty Intent you return via setResult(). Have you tried null here, instead?
Related
I have created an android app for the Portuguese (Brasil). This is one of my client's app. The client is getting feedback from the app users that they are not able to use the app properly or it goes back to start screen when they click on the button to import a contact from the Phonebook.
i.e. In the app, there are various places where I start the activity to get the result.
startActivityForResult(intent, requestCode);
Generally, I'm doing this from Fragments. And to pass the result from Activity to its Fragment, I'm doing like following:
#Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if (getSupportFragmentManager() != null) {
Fragment fragment = getFragment();
if (fragment != null)
fragment.onActivityResult(requestCode, resultCode, data);
}
}
So to check this problem We asked some of the users to check if they have Developer options enabled on their device. And Yes, they have it enabled on their devices. So we asked them to disable this and try the app and believe me it works.
I also have this option enabled on my device to test the app (Debugging) and I haven't faced any problem like this while using the app.
I don't understand this issue and I need to find the appropriate solution.
So I need your help to solve this problem.
Looking for the positive responses.
Thanks.
Try fragment context instead of getActivity() as you are starting activity from the fragment and result should be returnned to fragment.
Intent intent=new Intent(fragment.getContext(), Activity.class)
fragment.startActivityForResult(intent,REQUEST_CODE);
Finally, after a very long time, the issue is resolved.
When we have Don't keep Activities option enabled on the device and as soon as you leave the activity, it gets destroyed.
And in the onCreate, I was adding the initial fragment again.
But now I have added a check of
if(savedInstanceState == null)
// initial fragment here
else
// nothing to do
This check resolved the issue in my app. Hope it helps the others too.
I've worked with setResult(RESULT_OK, intent) for a while now, and am experiencing something strange.
MOST of the time, about 3/4 of the time that I enter an activity then exit from it using the following code which is ALWAYS executed:
Intent intent = new Intent();
intent.putExtra(KEY_ENVIRONMENT_SURVEY, esurvey);
setResult(RESULT_OK, intent);
finish();
In the activity being returned to, most of the time, RESULT_OK is returned, but sometimes RESULT_CANCELLED is returned, seemingly quite randomly. What could be causing this? Could finish() be called before the esurvey is attached (it's parcelable) and the default is RESULT_CANCELLED? If so how can I fix this? Use a handler and use postDelayed or check to see if RESULT_OK was set (I don't know how to do this, so please specify if that's the solution)?
Thanks!
Try to move this code into overridden finish() method. This will ensure it's called every time activity is finished.
#Override
public void finish() {
Intent intent = new Intent();
intent.putExtra(KEY_ENVIRONMENT_SURVEY, esurvey);
setResult(RESULT_OK, intent);
super.finish();
}
I'm revisiting this because I found the glitch in my application. The "back" button was very close to a button I had designated as moving to the next activity. I was allowing button presses to be registered after the first one, so sometimes the activity would seem to have completed by touching the "done" button, but was actually being navigated back to by the "back" button.
I fixed this using a boolean flag, checking to see if it was true upon a butotn press, and then setting it to true if it equaled false.
I read many threads about this subject, but I couldn't find anything that fits my needs.
I have an application with 3 activities (I'll call them screens here, more intuitive): A (MainActivity), B and C.
Screen A starts another process, retrieves some information from that process and sets the layout according to the answer. Then it gives you the opportunity to do something (write a text). This is done on OnCreate().
Screen B is not very interesting (presents the text and allows you to edit it).
Screen C has a single button which exits the application (basically starts the home activity). C also closes the process we started on A (after communicating some info to it).
So far so good.
The problem is that when I restart my app, I see screen C again. This is not good for me, because I want the user to be able to edit the text, without having to go back to the first or second screen (not because it's so difficult, but because I need him to see the new info presented on screen A before he does anything. And this can't be done after C, because after C he's done, unless he decides to start the app again).
This means that when I get to screen C and press the button, my app is completed and there's nothing left for me to do there (but start over fresh). But if my app was suspended on screen B, there's no need to start fresh - I can just go back to it and continue from there (regular Android behavior).
So I set android:clearTaskOnLaunch="true"but now I have two problems:
1. It now starts fresh again (sort of, see #2) even if the app was suspended on B, which is not what I need.
2. It's not really starting fresh.... Yes, I see screen A. But all the things I did on OnCreate() are not done again, which means my other process is not up and running, and then my app crashes because I have no one to talk to.....
Is there any solution to such cases?
I need to start fresh (but really fresh, with all the things I did on OnCreate() done again) only after previous run of the application was completed (we pressed the single button on screen C and got back to the home screen).
In any other case of suspension (in A, B, and even C if we didn't press the button yet) I want the normal Android behavior (i.e. go back to the same screen).
Any help will be much appreciated.
To solve this you can take advantage of the Android Activity Lifecycle: http://developer.android.com/training/basics/activity-lifecycle/stopping.html
Simply call finish() in Activity B and C in onStop() or onPause() appropriately to wipe away those activities (or "screens" as you say) when the app is closed. Activity A should reopen holding the last state when you open your app back up.
If you're looking to wipe out the last state in Activity A as well, then add a finish() call to it as well where appropriate (probably onStop or onPause again per your use case)
Good luck!
I had a similar app before, a survey app, and had the same situation. A->B->C and once you finish C you go straight to A and can't go back but you can go back from B->A. Here what I did:
1) Add this to A Activity when you start B Activity:
Intent start;
start = new Intent(MainActivity.this, RecordName.class);
startActivityForResult(start, 2);
and this method in your A activity:
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
if (requestCode == 2) {
if(resultCode == RESULT_OK){
//String result=data.getStringExtra("result");
finish();
}
}
2) In B Activity add this when you start C Activity:
Intent start;
start = new Intent(B.this, C.class);
startActivityForResult(start,1);
and this again in your B activity:
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
if (requestCode == 1) {
if(resultCode == RESULT_OK){
//String result=data.getStringExtra("result");
finish();
}
}
3) In your C activity add this to your press method:
Intent start;
start = new Intent(C.this,A.class);
// pass any data back to A activity
start.putExtra("Key", String);
startActivity(start);
// to close previous activities
Intent returnIntent = new Intent();
//returnIntent.putExtra("result","finish");
setResult(RESULT_OK,returnIntent);
// close current activity
finish();
I hope this helps
There are a lot of questions out there on similar topics, but after searching around I haven't found one that matches my issue.
I know about starting intents for result, and overriding onActivityResult() to handle these intents, but for some reason, I'm having issues when I'm coming back from activity b to activity a. So, for example, in the last of 3 activities (AddDirections class) I start in my project, I call this method to return back to the previous activity:
public void finish(View v){
Intent intent = new Intent(getApplicationContext(), AddIngredients.class);
intent.putExtra(Home.RECIPE_INTENT, (Parcelable)recipe);
intent.putExtra(Home.RECIPE_ID_INTENT, recipe.getId());
setResult(RESULT_OK, intent);
finish();
}
In the AddIngredients class, I have this method:
#Override
protected void onActivityResult(int requestCode, int resultCode, Intent data){
super.onActivityResult(requestCode, resultCode, data);
if(resultCode == RESULT_OK && requestCode == DIRECTIONS_REQUEST){
Intent intent = new Intent(getApplicationContext(), NameRecipe.class);
Recipe recipe = data.getParcelableExtra(Home.RECIPE_INTENT);
intent.putExtra(Home.RECIPE_INTENT, (Parcelable)recipe);
setResult(RESULT_OK, intent);
finish();
}
}
This should accept the returned result from the AddDirections class, and pass it off to NameRecipe, where I have the exact same method (Except for in the new Intent method it says Home.class). In the Home class, I have basically the same method again to receive the intent as it backs all the way out of the app.
Now, I will say that this works if I go straight through the steps from beginning to end. But if I use the up navigation to go the current activity's parent activity, then it messes everything up. Then when I click finish in the final step it messes up the resultCodes that I set for each intent. I make sure to explicitly set the correct result to RESULT_OK (which equals 1) but then for some reason, sometimes it changes what I've set to be the resultCode to be 0 instead.
Here's what I do in an activity if the user clicks the up navigation:
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
case android.R.id.home:
Intent intent = NavUtils.getParentActivityIntent(this);
intent.putExtra(Home.RECIPE_INTENT, (Parcelable)recipe);
setResult(RESULT_OK, intent);
NavUtils.navigateUpTo(this, intent);
finish(); //Have tried with and without this
return true;
}
return super.onOptionsItemSelected(item);
}
Like I said, I've searched for a lot of reasons why the resultCode gets overwritten after using the up navigation, but I haven't found a single reason why.
Any help would be greatly appreciated.
It looks like the underlying question is really how do I navigate between multiple activities through the stack using the up navigation that is built in. I am wondering if the project is setup correctly for this type of navigation. From the android developer resources, up navigation from google, you have to setup the navigation buttons with a parent activity. Then the application can traverse between the different activities. From what it looks like this should allow A->B B->C c->D and back to A if needed. I would also add in a button that would allow a direct path back to A if the user so chooses.
If you have more information on what you are trying to accomplish between activities whether it is data passed back and forth or just returning to the previous activity that would be helpful. Hopefully the link will help your issue with this.
your problem seems to be the NavUp, this util class tends to clear everything to navigate to the parent including your resultCode and the instance of the activity, resulting in a Canceled result (if started for result) to a new instance of the parent activity, in order to fix that a quick fix would be to declare android:launchMode="singleTop" in your manifest, but I wouldn't recommend to use that unless you are 100% that you want that, instead I would go into my navigator class, or my method for navigate and overwrite that specific navigation to something like:
Intent parentActivityIntent = NavUtils.getParentActivityIntent(this);
parentActivityIntent.setFlags(
Intent.FLAG_ACTIVITY_SINGLE_TOP | Intent.FLAG_ACTIVITY_CLEAR_TOP
);
NavUtils.navigateUpTo(this, parentActivityIntent);
Hope this helps!!
Sorry for the late answer :p
if by 'up navigation' you mean back key pressed then you need to override a function
#Override
public void onBackPressed() {
// TODO Auto-generated method stub
super.onBackPressed();
}
if from what it seems to be you are trying to get back when clicking an item from the Options Menu to your parent activity directly then i think you will need to go back step by step as at this moment there is already an activity running and waiting for a result so when you go directly to home activity its already waiting an answer from activity B and not activity C i hope i explained it right :)
I am trying to design a one time login system.
On the loginActivity the user enters a phone number to which I send a secret code thru SMS
On the confirmationActivity the user enters the secret code.
If the secret code is successful, I want to finish both confirmationActivity and loginActivity. To do that from loginActivity I do
Intent intent = new Intent(this, ConfirmationActivity.class);
startActivityForResult(intent, EXIT_CODE);
Then again in loginActivity I call
#Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if (resultCode == RESULT_OK) {
if (requestCode == EXIT_CODE) {
finish();
}
}
}
To test whether my system works, after registration, I click on the back button:
Expected behavior: Not being able to go back or close the app
Actual behavior: go back to the loginActivity (notice that it skips the confirmationActivity)
My hope is that once a user successfully registers they should never again get access to either the confirmationActivity or the loginActivity. And that when they close my app and restart it, it skips those two pages and take the user directly to the home page.
Note: It looks like the onActivityResult method is never called. I place a few println calls in there and they are never printed on LogCat.
DISCLAIMER: Last time I asked a question and showed a code snippet, one respondent got distracted and started talking about the snippet instead of addressing the question. The snippet here is just to show what I have tried. Obviously it has not solved the problem. Thank you.
One possible solution could be:
Instead of opening the app with LoginActivity you create a new one called FirstActivity.
In this activity you check if you have set a flag in sharedPreferences.
If this check is true then continue to your logged-in Activity.
If this check returns false start LoginActivity. After a User has succesfully entered the "secret", you should set a flag in the sharedPreferences. Next time the user opens the app the flag in sharedPreferences will be set a you will know that the user is already registered.
Any questions? comment below