2

I'm trying to use startActivityForResult(), I need to start an activity from a fragment, and then process the result in the original activity rather than the fragment that started it (when back is pressed). Can anyone tell me if this is possible or what my issue is?

Activity_A hosts Fragment_A, and the fragment can start Activity_B.

Fragment_A:

   Intent intent = new Intent(mContext, Activity_B.class);
   intent.putExtra(EXTRA_CHOSEN_BUSINESS, mChosenBusiness);
   intent.putExtra(EXTRA_CHOSEN_POSITION, position);
   getActivity().startActivityForResult(intent, 1);

Activity_B:

@Override
public void onBackPressed() {
    Intent intent = new Intent();
    intent.putExtra("myBoolean", wasUsingMap);
    setResult(RESULT_OK, intent);
    finish();
    super.onBackPressed();
}

Activity_A:

@Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
    if (requestCode == 1) {
        if(resultCode == RESULT_OK){
            mWasUsingMap = data.getBooleanExtra("myBoolean", false);
        }
    }
}

The data in this case is always null.

For testing I have tried not using getActivity().startActivityForResult(intent, 1); and simply using startActivityForResult(intent, 1); and the placing the onActivityResult in the fragment (with a call to the super onActivityResult in the activity following this answer) but the data is still null. I need it in the hosting activity anyway though if possible. I have also tried the top answer here and am still stumped..

(as a side note the boolean is used to detect which fragment should be displayed when the user presses back).

Community
  • 1
  • 1
Daniel Wilson
  • 18,838
  • 12
  • 85
  • 135

3 Answers3

5

I had a similar problem and the solution was actually easy to implement (hard to find though...)

In FragmentA call:

startActivityForResult(intent, 1); //not getActivity().startActivityForResult(intent, 1);

and override onActivityResult (inside the fragment)

@Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {

        if (requestCode == 1) {
            if (resultCode == RESULT_OK){
                //whatever
            }
            if (resultCode == RESULT_CANCELED) {
                //whatever
            }
        }
    }

Then, on ActivityB do something like this:

@Override
public boolean onOptionsItemSelected(MenuItem item) {

    int id = item.getItemId();
    switch (id) {
        case android.R.id.home:
            Log.e("home button", "pressed");
            Intent returnIntent = new Intent();
            returnIntent.putExtra("result",mResult);
            setResult(RESULT_OK, returnIntent);
            finish();
            super.onBackPressed();
            return true;
        case R.id.others:
            //whatever

    }

    return super.onOptionsItemSelected(item);
}
Carlos Borau
  • 1,433
  • 1
  • 24
  • 34
2
super.onBackPressed();

shouldn't be the first statement, once it is called, the rest of the body of the method is unreachable.

EDIT

From a fragment, you should start another activity like this:

Intent intent = new Intent(getActivity(), Activity_B.class);
// put data
startActivityForResult(intent, 1);
Sergo Pasoevi
  • 2,833
  • 3
  • 27
  • 41
  • I spotted that yeah thanks, the data passed in is still null though, I've had a breakpoint on that line so that's how I knew it was still messed up. Will make that change now – Daniel Wilson Feb 13 '14 at 12:46
  • Why do you call `super.onActivityResult(requestCode, resultCode, data);` ? If you decide to consume onActivityResult yourself, there's no need to call super. – Sergo Pasoevi Feb 13 '14 at 12:48
  • EDIT: Sorry I misread your answer there, interesting. If I call super.onBackPressed(); first it was reaching the rest of the statement (it was triggering a breakpoint), and if I call it last, the onActivityResult doesn't seem to be triggered at all so now I'm extra confused :) I believe the super onActivityResult is there from testing other answers - removed but still broken. I'll update the code to reflect those important changes though thanks. – Daniel Wilson Feb 13 '14 at 12:57
  • If you call `finish()`, you no longer need to call onBackPressed. – Sergo Pasoevi Feb 13 '14 at 12:58
  • Okay, well is there some other line I need in order to force the intent to be sent back with the data? When I hit a breakpoint placed super.onBackPressed(), the next breakpoint (in onActivityResult) was hit with the data. If I leave the code as is but remove the breakpoint at super.onBackPressed() it does not work - leading me to believe it is some kind of threading issue. If I totally remove the call to super.onBackPressed() (which you are right shouldn't be necessary), it does not trigger either. – Daniel Wilson Feb 13 '14 at 13:16
  • Do you necessarily need to do passing result back on `onBackPressed`? You could juts create something like `sendData()` and call it from anywhere you wish. (In that method you'd include sending back the result and calling `finish()`. – Sergo Pasoevi Feb 13 '14 at 13:18
  • Yes I think I'll have to find some other solution - I need it in onBackPressed though yeah - basically it's being used to remember which tab I was on in Activity_A so I can go back to the same one if someone hits back (hardware or action bar). – Daniel Wilson Feb 13 '14 at 13:25
0

My issue was to do with the logic of using the Up caret in the action bar vs. using the back button. Previously I had called onBackPressed() when the up caret was hit, but this was not necessary.

The result rather confusingly was that the hardware back button successfully returned a result with the code above plus the changes suggested by user Fremmedehenvendelser, but the Up caret did not even though it would also enter onBackPressed().

Replacing the call to onBackPressed() when the home caret is hit (in Activity_B's parent):

@Override
public boolean onOptionsItemSelected(MenuItem item) {

    if (mDrawerToggle.onOptionsItemSelected(item)) {
        return true;
    }

    if (item.getItemId() == android.R.id.home){
        onBackPressed();
    }

    // Handle your other action bar items...
    return super.onOptionsItemSelected(item);
}

With this (in Activity_B) seems to work nicely for me:

@Override
public boolean onOptionsItemSelected(MenuItem item) {

    if (item.getItemId() == android.R.id.home){

        getDrawerToggle().setDrawerIndicatorEnabled(true);

        Intent intent = new Intent();
        intent.putExtra("myBoolean", wasUsingMap);
        if (getParent() == null) {
            setResult(RESULT_OK, intent);
        } else {
            getParent().setResult(RESULT_OK, intent);
        }

        finish();
    }

    return super.onOptionsItemSelected(item);
}

Interestingly it seems be essential that getDrawerToggle().setDrawerIndicatorEnabled(true); is called otherwise the result is not sent back (this line is in onBackPressed() too).

Daniel Wilson
  • 18,838
  • 12
  • 85
  • 135