setResult does not work when BACK button pressed
Asked Answered
F

10

115

I am trying to setResult after the BACK button was pressed. I call in onDestroy

Intent data = new Intent();
setResult(RESULT_OK, data) 

But when it comes to

onActivityResult(int requestCode, int resultCode, Intent data) 

the resultCode is 0 (RESULT_CANCELED) and data is 'null'.

So, how can I pass result from activity terminated by BACK button?

Forced answered 20/4, 2010 at 22:53 Comment(0)
F
11

I refactored my code. Initially I prepared some data and set it as activity result in onDestroy (this did not work). Now I set activity data each time the data to be returned is updated, and have nothing in onDestroy.

Forced answered 22/4, 2010 at 3:3 Comment(2)
This does not work for me since my data is update in "onPause"Rawalpindi
If your activity gets recreated after you call setResult(), your data will be lost.Lonnielonny
K
169

You need to overide the onBackPressed() method and set the result before the call to superclass, i.e

@Override
public void onBackPressed() {
    Bundle bundle = new Bundle();
    bundle.putString(FIELD_A, mA.getText().toString());
    
    Intent mIntent = new Intent();
    mIntent.putExtras(bundle);
    setResult(RESULT_OK, mIntent);
    super.onBackPressed();
}
Kuomintang answered 2/6, 2011 at 9:21 Comment(5)
Do note that if you use this approach the super.onBackPressed() invocation must happen after the call to setResult() as shown above or you will have the original problem all over again!Hypoglycemia
That's best answer here. If we override onPause() or onDestroy(), onBackPressed() will be called first and it will set result to 0. Please be aware of that!Lucila
or you can set the default result in onCreate. Any place before finish() is fine.Incomprehension
I implemented similar approach but it still not working. FOr instance I have the request code and the intent working but the resultCode is always 0.Navigation
it is Dec,2020 And still it works! thanksWhole
P
74

Activity result must be set before finish() is called. Clicking BACK actually calls finish() on your activity, so you can use the following snippet:

@Override
public void finish() {
    Intent data = new Intent();
    setResult(RESULT_OK, data); 

    super.finish();
}

If you call NavUtils.navigateUpFromSameTask(); in onOptionsItemSelected(), finish() is called, but you will get the wrong result code. So you have to call finish() not navigateUpFromSameTask in onOptionsItemSelected(). wrong requestCode in onActivityResult

Puffball answered 9/3, 2011 at 12:18 Comment(4)
This works in the OPs case, but not in general, right? There are more methods than finish() that induce the end of the app lifecycle (via onPause() and onDestroy())? Also see my comment at the other answer.Whopper
And even if there weren't, you wouldn't know about it when it would be introduced in an API update. Not as easily as you would when behavior of onPause() or onDestroy() changed. Those are the methods you are supposed to override.Whopper
@Whopper - I don't get your point, what finish has to do with onPause and onDestroy? Those are totally not related except for that finish starts the termination process which onPause and onDestroy are part of.Puffball
This is the only solution that works now afaik on minSdk 26 / targetSdk 32 overriding onBackPressed doesn't seem to work anymore.Raymer
D
21

If you want to set some custom RESULT_CODE in onBackPressed event then you need to first set the result and then call the super.onBackPressed() and you will receive the same RESULT_CODE in the caller activity's onActivityResult method

    @Override
    public void onBackPressed()
    {
         setResult(SOME_INTEGER);
         super.onBackPressed();
    }
Drops answered 4/3, 2014 at 13:36 Comment(0)
F
11

I refactored my code. Initially I prepared some data and set it as activity result in onDestroy (this did not work). Now I set activity data each time the data to be returned is updated, and have nothing in onDestroy.

Forced answered 22/4, 2010 at 3:3 Comment(2)
This does not work for me since my data is update in "onPause"Rawalpindi
If your activity gets recreated after you call setResult(), your data will be lost.Lonnielonny
E
4

You should override onOptionsItemSelected like this:

@Override
public boolean onOptionsItemSelected(final MenuItem item) {
    switch (item.getItemId()) {
    case android.R.id.home:
        final Intent mIntent = new Intent();
        mIntent.putExtra("param", "value");
        setResult(RESULT_OK, mIntent);
        finish();
        return true;
    default:
        return super.onOptionsItemSelected(item);
    }
}
Expectoration answered 6/12, 2012 at 11:52 Comment(0)
P
2

Refer onActivityResult(int, int, Intent) doc

Solution is to check the resultCode for value Activity.RESULT_CENCELED. If yes, then it means that either BACK was pressed or the activity crashed. Hope it works for you guys, works for me :).

Painter answered 18/3, 2011 at 13:2 Comment(1)
This is the exact solution.. You have to Result Code.. No one can set the result other than you in the code. So , if result is not OK means either its back presses Or Crashed..Fourscore
M
0

onDestroy is too late in the chain — instead override onPause and check isFinishing() to check if your activity is at the end of its lifecycle.

Manic answered 21/4, 2010 at 0:9 Comment(5)
Nope, this is too late as well.Forced
I actually call this a bug: code.google.com/p/android/issues/detail?id=1671. In complex applications I think due to this there is just some behavior you can't program.Whopper
It is also very counterintuitive. So much that I keep making the same mistake, over a period of 2 years now already.Whopper
Actually - this is even worse. And it exists in JB as I'm coding. If I call setResult from onPause it is executed but nether resultCode nor data is set when onActivityReturn is executed. Why?Rawalpindi
And that's why: "Implementations of this method (onPause) must be very quick because the next activity will not be resumed until this method returns" goo.gl/8S2YRawalpindi
A
0

Try overriding onBackPressed (from android level 5 up), or override onKeyDown() and catch KeyEvent.BUTTON_BACK (see Android Activity Results) This does the trick for me.

Accrue answered 19/5, 2011 at 8:13 Comment(0)
R
0

Don't rely on any logic executed in onPause of one activity when you return to the initial one. According to the docs:

Implementations of this method (onPause) must be very quick because the next activity will not be resumed until this method returns

See http://goo.gl/8S2Y for details.

The safest way is to set result after each result altering operation is complete (as you mention in your answer)

Rawalpindi answered 22/7, 2012 at 17:57 Comment(0)
H
0

i paste the answer may be will be helpful to other people: when a set launcheMode with android:launchMode="singleTask" i also cant get the result, the doc says:

     /* <p>Note that this method should only be used with Intent protocols
 * that are defined to return a result.  In other protocols (such as
 * {@link Intent#ACTION_MAIN} or {@link Intent#ACTION_VIEW}), you may
 * not get the result when you expect.  For example, if the activity you
 * are launching uses the singleTask launch mode, it will not run in your
 * task and thus you will immediately receive a cancel result.
 */

and:

     /* <p>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. 
 */
Hey answered 15/4, 2013 at 16:18 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.