11

The structure of the app is like this:

tabHost (in Activity) -> contains -> TabFragment(extend base container fragment)

1. The code in Activity:

tabHost.addTab(
                tabHost.newTabSpec("home").setIndicator("",
                        getResources().getDrawable(R.drawable.btn_home)),
                HomeFragment.class, null);

2. The code in HomeFragment (Notice that HomeFragment is not the actual function but a container like this, and it extend BaseContainerFragment):

public class HomeFragment extends BaseContainerFragment {

    public Home homeFrag;
    private boolean mIsViewInited;

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
        return inflater.inflate(R.layout.container_fragment, null);
    }

    @Override
    public void onActivityCreated(Bundle savedInstanceState) {
        super.onActivityCreated(savedInstanceState);
        if (!mIsViewInited) {
            mIsViewInited = true;
            initView();
        }
    }

    private void initView() {
        homeFrag = new Home();
        replaceFragment(homeFrag, false);
    }

}

3. BaseContainerFragment

public class BaseContainerFragment extends Fragment {

    public void replaceFragment(Fragment fragment, boolean addToBackStack) {
        FragmentTransaction transaction = getChildFragmentManager().beginTransaction();
        if (addToBackStack) {
            transaction.addToBackStack(null);
        }
        transaction.replace(R.id.container_framelayout, fragment);
        transaction.commit();
    }

    public boolean popFragment() {
        boolean isPop = false;
        if (getChildFragmentManager().getBackStackEntryCount() > 0) {
            isPop = true;
            getChildFragmentManager().popBackStack();
        }
        return isPop;
    }

}

4. In the Home (The actual content of the fragment)

UploadType fragment = new UploadType();
                    Bundle bundle = new Bundle();
                    bundle.putString("form_type", "request");
                    fragment.setArguments(bundle);
                    ((BaseContainerFragment)getParentFragment()).replaceFragment(fragment, true);

5. And in the UploadType , I call the camera activity but onActivityResult is only return in the main activity.

startActivityForResult(intent, REQUEST_CAMERA);

public void onActivityResult(int requestCode, int resultCode, Intent data) {
        Log.d("test1", "result2");
        super.onActivityResult(requestCode, resultCode, data);
}

How can I trigger the onActivityResult at UploadType? Thanks for help.

user782104
  • 13,233
  • 55
  • 172
  • 312
  • 1
    Fragments don't handle onActivityResult, but the activity – Héctor Feb 13 '15 at 09:50
  • 1
    try this startActivityFromFragment(YourFragment.this, intent, REQUEST_CAMERA); – SathishKumar Feb 13 '15 at 09:51
  • Thanks for helping. Then is there any way to call the fragment onActivityResult function inside main? Since I have switch the fragment (from Home() to UploadTab() , how can I get that fragment ? thanks) – user782104 Feb 13 '15 at 09:53
  • try UploadForm.this.startActivityFromFragment or getActivity().startActivityFromFragment but both undefined? – user782104 Feb 13 '15 at 09:57
  • @user782104: `onActivityResult` is define in Activity instead of in Fragment – ρяσѕρєя K Feb 16 '15 at 07:03
  • startActivityForResult where you call in UploadType or your activity – Lokesh Feb 16 '15 at 11:35
  • did you try adding `super.onActivityResult()`? – Droidekas Feb 18 '15 at 07:47
  • Check this post [startActivityForResult() from a Fragment and finishing child Activity, doesn't call onActivityResult() in Fragment](http://stackoverflow.com/questions/17085729/startactivityforresult-from-a-fragment-and-finishing-child-activity-doesnt-c) – Xcihnegn Feb 18 '15 at 08:04
  • see accepted answer and discussion of http://stackoverflow.com/questions/6147884/onactivityresult-not-being-called-in-fragment – Lokesh Feb 19 '15 at 08:13
  • see accpeted answer and discussion of http://stackoverflow.com/questions/6147884/onactivityresult-not-being-called-in-fragment – Lokesh Feb 19 '15 at 08:15
  • see accepted answer and discussion of this [onactivityresult-not-being-called-in-fragment][1] [1]: http://stackoverflow.com/questions/6147884/onactivityresult-not-being-called-in-fragment – Lokesh Feb 19 '15 at 08:16
  • Also make sure your hostActivity launch mode not set to singleTask or singleInstance http://stackoverflow.com/a/38760091/3496570 – Zar E Ahmer Aug 04 '16 at 06:39
  • 3
    Possible duplicate of [onActivityResult is not being called in Fragment](https://stackoverflow.com/questions/6147884/onactivityresult-is-not-being-called-in-fragment) – aya salama Nov 05 '17 at 10:49

6 Answers6

31

The reason why this doesn't work is because you are calling startActivityForResult() from within a nested fragment. Android is smart enough to route the result back to an Activity and even a Fragment, but not to a nested Fragment hence why you don't get the callback. (more information to why that doesn't work here or on stackoverflow)

Now in order to make it work I suggest you manually route the callback to the ChildFragment (=UploadType) in the ParentFragment (=BaseContainerFragment):

protected void onActivityResult(int requestCode, int resultCode, Intent data) {
    Fragment uploadType = getChildFragmentManager().findFragmentById(R.id.container_framelayout);

    if (uploadType != null) {
        uploadType.onActivityResult(requestCode, resultCode, data);
    }
    super.onActivityResult(requestCode, resultCode, data);
}
Jeroen Mols
  • 3,436
  • 17
  • 24
  • http://inthecheesefactory.com/blog/how-to-fix-nested-fragment-onactivityresult-issue/en – John Sep 21 '15 at 09:24
13

In my case, I've done by adding following code in my MainActivity.java

@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
    super.onActivityResult(requestCode, resultCode, data);

    for (Fragment fragment : getSupportFragmentManager().getFragments()) {
        fragment.onActivityResult(requestCode, resultCode, data);
    }
}
Kasim Rangwala
  • 1,765
  • 2
  • 23
  • 44
9

In your Activity Override onActivityForResult() like this

@Override
    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
        super.onActivityResult(requestCode, resultCode, data);
    }

Now in your fragment u can get the activity result inside this

@Override
    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
      Log.d("test1", "result2");
    }

Make sure when your are calling start ActivityForResult in your frragment it should be like this

startActivityForResult(intent, REQUEST_CAMERA);
williamj949
  • 11,166
  • 8
  • 37
  • 51
  • Thanks a lot, should I put the onActivityResult inside the BaseContainerFragment / HomeFragment as well? – user782104 Feb 13 '15 at 10:10
  • 1
    Put onActivityResult from where you are calling startActivtyForResult – williamj949 Feb 13 '15 at 10:12
  • Thanks. one more question, what if more than one fragment has startActivityForResult? – user782104 Feb 13 '15 at 10:15
  • 1
    Did the solution work?If yes then accept the answer.You ca filter the result based on the Requestcode ie in your case REQUEST_CAMERA – williamj949 Feb 13 '15 at 10:18
  • Thanks for your patience. yes and if my case has fragmentA call camera , and fragmentB call photo album , both need the onActivityResult , how can I keep two onActivityResult? – user782104 Feb 13 '15 at 10:22
  • 1
    Put different request code for your different intents.Also close the answer – williamj949 Feb 13 '15 at 10:22
  • that means it call both onActivityResult function? and it didn't call the onActivityResult function in fragment . Sorry, is there any way to debug? – user782104 Feb 13 '15 at 10:24
6

For NavHostFragment of Navigation Architecture Component

If you are using single activity and have fragments inside the NavHostFragment, there is an issue of onActivityResult() of the child fragment of NavHostFragment not getting called.

To fix this issue, you need to call the onActivityResult() of the child fragments manually from inside the onActivityResult() of the host activity. The host activity is the activity that hosts your NavHostFragment.

Here's the Kotlin code for onActivityResult() of your host activity:

override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
    super.onActivityResult(requestCode, resultCode, data)
    val navHostFragment = supportFragmentManager.findFragmentById(R.id.your_nav_host_fragment)
    val childFragments = navHostFragment?.childFragmentManager?.fragments
    childFragments?.forEach { it.onActivityResult(requestCode, resultCode, data) }
}
Yogesh Umesh Vaity
  • 41,009
  • 21
  • 145
  • 105
0

TabActivity->ActivityA->FragmentB, it's not work.

use a bad bad bad way:

ActivityA.java

public void onSelectSomething(){

    ...

    startActivityForResult(intent, 22222);
}

@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
    if (mFragment != null) {
        mFragment.onActivityResult(requestCode, resultCode, data);
    }
}

FragmentB.java

if(getActivity() instanceof ActivityA) {
    ((RepairerListActivity)getActivity()).onSelectSomething();
} 


@Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
    super.onActivityResult(requestCode, resultCode, data);
    if (requestCode == 22222) {
        // do things
    }
}   
qinmiao
  • 5,559
  • 5
  • 36
  • 39
0
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
    super.onActivityResult(requestCode, resultCode, data);

    // Loop through all child fragments of the activity
    for (Fragment fragment : getSupportFragmentManager().getFragments()) {

        // check if the current fragment is YourFragment
        if (fragment instanceof YourFragment ) {
            fragment.onActivityResult(requestCode, resultCode, data);
        }

    }
}