986

The activity hosting this fragment has its onActivityResult called when the camera activity returns.

My fragment starts an activity for a result with the intent sent for the camera to take a picture. The picture application loads fine, takes a picture, and returns. The onActivityResult however is never hit. I've set breakpoints, but nothing is triggered. Can a fragment have onActivityResult? I'd think so since it's a provided function. Why isn't this being triggered?

ImageView myImage = (ImageView)inflatedView.findViewById(R.id.image);
myImage.setOnClickListener(new OnClickListener() {
    @Override
    public void onClick(View view) {
        Intent cameraIntent = new Intent(android.provider.MediaStore.ACTION_IMAGE_CAPTURE);
        startActivityForResult(cameraIntent, 1888);
    }
});

@Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
    if( requestCode == 1888 ) {
        Bitmap photo = (Bitmap) data.getExtras().get("data");
        ((ImageView)inflatedView.findViewById(R.id.image)).setImageBitmap(photo);
    }
}
Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Spidy
  • 39,723
  • 15
  • 65
  • 83
  • 2
    check this post, there is problem description and common workaround solution: http://stackoverflow.com/questions/6147884/onactivityresult-not-being-called-in-fragment/#24303360 – Oleksii K. Jun 19 '14 at 09:35
  • 6
    Any one else reading this make sure you pass `requestCode >= 0`! – Muhammad Babar Aug 26 '15 at 10:35
  • 3
    Also make sure your Activity LauchMode must not singleInstance or singleTask. otherwise onActivityResult will not called – Zar E Ahmer Aug 05 '16 at 10:56
  • See this link may help you:https://www.androidtutorialonline.com/onactivityresult-in-fragment/ – Android Tutorial Sep 17 '18 at 07:47
  • 1
    We need to redirect the onActivityResult in the Activity to the Fragment. Refer this link: https://www.codexpedia.com/android/onactivityresult-not-called-in-nested-fragment/ – Reejesh PK Dec 10 '18 at 11:51
  • How are you even able to call ```startActivityForResult(cameraIntent, 1888);``` from a Fragment. Fragments are pieces of a layout and can't interact with the activity's operation unless you intended to do so. You can call ```getActivity().startActivityForResult(cameraIntent, 1888);``` And when the result returns pass it to the fragment ```fragment.onActivityResult(-,-,-)``` – Ian Elvister Mar 11 '21 at 19:10

40 Answers40

1349

The hosting activity overrides onActivityResult(), but it did not make a call to super.onActivityResult() for unhandled result codes. Apparently, even though the fragment is the one making the startActivityForResult() call, the activity gets the first shot at handling the result. This makes sense when you consider the modularity of fragments. Once I implemented super.onActivityResult() for all unhandled results, the fragment got a shot at handling the result.

And also from @siqing answer:

To get the result in your fragment make sure you call startActivityForResult(intent,111); instead of getActivity().startActivityForResult(intent,111); inside your fragment.

Pankaj Lilan
  • 4,245
  • 1
  • 29
  • 48
Spidy
  • 39,723
  • 15
  • 65
  • 83
  • 2
    I have the same issue but I don't understand how you fixed this? – Codejoy Jul 07 '11 at 21:27
  • 37
    In your activity's onActivityResult, call super.onActivityResult() – Spidy Jul 08 '11 at 05:40
  • Sorry but it's nor working for me... @Override public void onActivityResult(int requestCode, int resultCode, Intent data) { super.onActivityResult(requestCode, resultCode, data); } wont send onActivityResult to my fragments... – StErMi Jan 14 '12 at 09:38
  • @StErMi Did you call `startActivityForResult()` in your fragments? I guess if you call that method in activity, it won't notify its fragments... Just guessing... –  May 26 '12 at 14:57
  • @Spidy: +1 for your answers.. such a small thing but ignored by me. thanks – Zoombie Jul 01 '12 at 12:55
  • 175
    @StErMi Make sure you call startActivityForResult() and not getActivity().startActivityForResult() from your fragment. See siqing answer below. – OferR Aug 08 '12 at 19:07
  • 8
    There appears to be a related bug, where the support library is being used http://code.google.com/p/android/issues/detail?id=15394 – Ollie C Aug 09 '12 at 14:15
  • 86
    Also note that if you are using nested fragments, the child fragment should call `getParentFragment().startActivityForResult` so that the parent fragment will have its onActivityResult method called. – Eric Brynsvold Sep 10 '13 at 15:58
  • was this issue fixed on newer support library versions? – android developer Nov 23 '13 at 15:25
  • it may have been, this question/answer was created in the 3.0 era – Spidy Nov 25 '13 at 19:09
  • 5
    I have super.onActivityResult in both Fragment and Activity. Still doesn't work either way :( – emen Mar 05 '14 at 05:04
  • 2
    @OferR but then there is the issue with the wrong request code being returned. – user1940676 Mar 18 '14 at 08:49
  • This got me close to solving my problem, but i already had `super.onActivityResult()` in my host activity. Please view my answer below for another solution that is working. – prolink007 Jun 08 '14 at 15:06
  • 8
    @EricBrynsvold was right, startActivityForResult doesn't work in nested fragments. For this, you'd better call getParentFragment().startActivityForResult(), and in that parent fragment, then, you can implement onActivityResult() and in that method deliver the result to the child fragmen, ie: childFragment.getParentFragment().onActivityResult(requestCode, resultCode, data) – edrian Jan 07 '15 at 19:28
  • 1
    I find that calling `startActivityForResult()` from my Fragment then having `super.onActivityResult()` in my `FragmentActivity` makes ALL fragments in the `getFragmentManager()` have their `onActivityResult()` called. Ensuring that ALL requestCodes are unique. – Unknownweirdo Mar 30 '15 at 15:08
  • If you are using ViewPager, apart from doing what this answer says, you also need to do what @Oleksii Kropachov says. Combining both approaches solved my problem. – Bitcoin Cash - ADA enthusiast Apr 29 '15 at 03:45
  • what to do if I want to call startActivityForResult from static method in my fragment? Please help me in this. – Shreyash Mahajan Oct 30 '15 at 06:24
  • Thanks, Spidy. This problem certainly could have cost me hours. No doubt that this answer will get you a ton of points on stackoverflow for many years to come ! – Someone Somewhere Dec 17 '15 at 15:04
  • I believe that if the Activity extends android.app.Activity and not FragmentActivity, the `onActivityResult` base method does nothing. Even in API 24. – androidguy Nov 23 '16 at 08:15
  • @Spidy adding super.onActivityResult(requestCode, result, intent) in Activity not working for me. – Nishant Bhakta Nov 07 '17 at 15:17
  • Also, note that if you are handling sending the result in onBackPressed() method then you shouldn't call `super.onBackPressed()` – Deepak Kumar Jun 20 '19 at 13:02
  • I wanted to start intent in my adapter, and i tried every method but didn't work, at last i declared a callback interface in my adapter and i start intent in my fragment and its fixed. – masoud jafari Feb 17 '21 at 07:07
359

I think you called getActivity().startActivityForResult(intent,111);. You should call startActivityForResult(intent,111);.

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
siqing
  • 3,599
  • 1
  • 13
  • 2
  • 3
    I also had the same problem with `RingtonePreference` located in `PreferenceFragment`. Unfortunately, `RingtonePreference` calls `getActivity().startActivityForResult()`, and I did not get results even though I call `super.onActivityResult` in the activity's `onActivityResult`. I was compelled to create a derived from `RingtonePreference` class, which binds itself to the `PreferenceFragment` and calls `fragment.startActivityForResult()`. – Stan Nov 27 '13 at 12:12
  • @siqing I am not able to call startActivitForResult from my static method. Any solution for that? I must need to use activity.startActivityForResult. Please help me in this – Shreyash Mahajan Oct 30 '15 at 06:26
316

Option 1:

If you're calling startActivityForResult() from the fragment then you should call startActivityForResult(), not getActivity().startActivityForResult(), as it will result in fragment onActivityResult().

If you're not sure where you're calling on startActivityForResult() and how you will be calling methods.

Option 2:

Since Activity gets the result of onActivityResult(), you will need to override the activity's onActivityResult() and call super.onActivityResult() to propagate to the respective fragment for unhandled results codes or for all.

If above two options do not work, then refer to option 3 as it will definitely work.

Option 3:

An explicit call from fragment to the onActivityResult function is as follows.

In the parent Activity class, override the onActivityResult() method and even override the same in the Fragment class and call as the following code.

In the parent class:

@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
    Fragment fragment = getSupportFragmentManager().findFragmentById(R.id.dualPane);
    fragment.onActivityResult(requestCode, resultCode, data);
}

In the child class:

@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
    // In fragment class callback
}
Vinayak
  • 6,056
  • 1
  • 32
  • 30
  • 6
    This worked for me. It's a nasty workaround, but I don't have a better idea to solve this idiotic bug... – Bogdan Zurac Jun 21 '13 at 13:35
  • @Vivky, Your answer worked for me. But there is one more issue I am facing, instead of `setResult(); finish();` when I press back from second activity then also `onActivityResult` gets called with provided `RESULT_CODE`. – snehal_penurkar Aug 09 '15 at 10:12
  • superb answer. I implemented the third solution to get it done. – Sash_KP Oct 13 '15 at 09:50
  • I think the solution 3 would work for me but the `onActivityResult()` of the activity returns a weird `requestCode` which is passed to my fragment and then ignored =/ – E-Kami Jan 21 '16 at 20:28
  • @Happy Vicky this means that even when startActivityForResult() is called from a fragment, the result is received and can be handled in the activity? – notGeek Feb 06 '18 at 18:47
  • 2
    @notGeek You are correct . Result is always recived in Activity even though you called from fragment or activity . – Vinayak Feb 07 '18 at 10:29
  • in child class, it should be `public void onActivityResult(int requestCode, int resultCode, Intent data) {` not `protected` – Shailendra Madda Mar 07 '18 at 07:31
  • actually, it depends `@ShylendraMadda, when we call things protected we immediately lookup the concept of scope of access. i think the author here intended protected. – EvOlaNdLuPiZ Feb 23 '19 at 08:27
  • If you are using Android Navigation Component you should see this answer https://stackoverflow.com/questions/6147884/onactivityresult-is-not-being-called-in-fragment/58987665#58987665 – Mohit Mehta Nov 22 '19 at 04:47
  • This worked for me. It was just change getFragmentManager() to getSupportFragmentManager() in Activity and the fragment wasn't null anymore. – Rodrigo Jardim Aug 08 '20 at 18:41
115

In case you don't know fragments in your activity just enumerate them all and send activity result arguments:

//Java

// In your activity
@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);
    }
}

//Kotlin

override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
        super.onActivityResult(requestCode, resultCode, data)
        for (fragment in supportFragmentManager.fragments) {
            fragment.onActivityResult(requestCode, resultCode, data)
        }
    }
Vladislav Varslavans
  • 2,775
  • 4
  • 18
  • 33
ruX
  • 7,224
  • 3
  • 39
  • 33
  • 3
    Damn, I thought i just found the simpliest solution, but there is no such method as getFragments(). – WindRider May 09 '14 at 09:56
  • 2
    @WindRider There is. If you use Android support library (AppCompat). – dasar Oct 28 '14 at 10:12
  • 2
    Also, I learned the hard way that you have to check if the fragment in the array is not a reference to itself! ` if(fragment!=this) { fragment.onActivityResult(requestCode, resultCode, data); ` – reubenjohn Feb 11 '15 at 17:57
  • This doesn't work if the fragments are nested, as only the top fragment will be in the list. I believe that super.onActivityResult() is already calling onActivityResult() on all of the fragments in the list, so this idea is redundant. – BeccaP Sep 02 '15 at 16:52
  • http://stackoverflow.com/questions/27343945/onactivityresult-of-an-activity-not-called-after-startactivityforresult-of-fragm/34018432#34018432 – maruti060385 Dec 01 '15 at 10:46
  • what about "android.app.Fragment" ? how to get all fragments ? – Rajesh Satvara Sep 10 '16 at 07:08
  • @RjzSatvara for native fragments implementation I used callbacks, broadcasts and message busses – ruX Sep 10 '16 at 08:46
  • Always check for null fragment in fragmentManager. Learnt this the hard way. Copied this code and crashed the app. – VipulKumar Sep 29 '16 at 06:34
  • If you are using Android Navigation Component you should see this answer https://stackoverflow.com/questions/6147884/onactivityresult-is-not-being-called-in-fragment/58987665#58987665 – Mohit Mehta Nov 22 '19 at 04:46
86

I'm having this same problem with the ChildFragmentManager. The manager will not pass the result to the nested fragment, you have to do that manually in your base fragment.

public void onActivityResult(int requestCode, int resultCode, Intent intent) {
    super.onActivityResult(requestCode, resultCode, intent);
    Fragment fragment = (Fragment) getChildFragmentManager().findFragmentByTag(childTag);
    if (fragment != null) {
        fragment.onActivityResult(requestCode, resultCode, intent);
    }
}
Piyush
  • 18,895
  • 5
  • 32
  • 63
MinceMan
  • 7,483
  • 3
  • 38
  • 40
  • 1
    If you have your child Fragment as a private member, then use `Fragment fragment = myChildFragment;` to replace the above `findFragmentByTag` line of code. The rest can be kept unchanged. – lcn Nov 20 '13 at 05:22
  • 7
    I guess I would strongly recommend against keeping a fragment as a private member. They have their own lifecycle so you never know if their in a good state to interact with, the manager does. Also they're pretty hefty and I would be concerned about memory leaks. The manager wouldn't have been created if you didn't need to use it. – MinceMan Nov 21 '13 at 23:54
75

Original post.

FragmentActivity replaces requestCode by a modified one. After that, when onActivityResult() will be invoked, FragmentActivity parses the higher 16 bits and restores the index of the original Fragment. Look at this scheme:

Enter image description here

If you have a few fragments at the root level there are no problems. But if you have nested fragments, for example Fragment with a few tabs inside ViewPager, you guaranteed will face with a problem (or already faced it).

Because only one index is stored inside requestCode. That is index of Fragment inside its FragmentManager. When we are using nested fragments, there are child FragmentManagers, which have their own list of Fragments. So, it's necessary to save the whole chain of indices, starting from root FragmentManager.

Enter image description here

How do we resolve this issue? There is common workaround solution in this post.

GitHub: https://github.com/shamanland/nested-fragment-issue

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Oleksii K.
  • 5,359
  • 6
  • 44
  • 72
  • I have same issue as I used a ViewPager in parent fragment which holds other fragments as tabs. Tried using the nested-fragment-issue but ended up with compilation erros. Can you suggest me the solution ? Raised an issues too here https://github.com/shamanland/nested-fragment-issue/issues/2 – cgr Nov 13 '15 at 11:12
  • I answered on github, so let's move this conversation out of here https://github.com/shamanland/nested-fragment-issue/issues/2#issuecomment-156402156 – Oleksii K. Nov 13 '15 at 11:25
  • Thanks! If it is not a recommended solution, I suggest edit the answer accordingly so that one need not to spend time trying this to know it has compilation erros. – cgr Nov 13 '15 at 14:19
24

For those who use Android Navigation Component should use in Activity's onActivityResult(...) the primaryNavigationFragment to get it's fragment reference and call fragment's fragment.onActivityResult(...).

Here's Activity's onActivityResult(...)

@Override
public void onActivityResult(int requestCode, int resultCode, Intent imageData)
{
    super.onActivityResult(requestCode, resultCode, imageData);

    for (Fragment fragment : getSupportFragmentManager().getPrimaryNavigationFragment().getChildFragmentManager().getFragments())
    {
            fragment.onActivityResult(requestCode, resultCode, imageData);
    }
}
Mohit Mehta
  • 1,283
  • 12
  • 21
  • 1
    This works with Android Navigation Component. Other answers didn't work for me as I also use Android Navigation Component – Aimkiller Feb 15 '22 at 17:58
18

FOR MANY NESTED FRAGMENTS (for example, when using a ViewPager in a fragment)

In your main activity:

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

In your fragment:

@Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
    for (Fragment fragment : getChildFragmentManager().getFragments()) {
        fragment.onActivityResult(requestCode, resultCode, data);
    }
}

In your nested fragment

Call activity

getParentFragment().startActivityForResult(intent, uniqueInstanceInt);

uniqueInstanceInt - replace it with an int that is unique among the nested fragments to prevent another fragment treat the answer.

Receive response

@Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
    if (requestCode == uniqueInstanceInt ) {
        // TODO your code
    }
}

Attention

A number between 0 and 65536 need be used in uniqueInstanceInt for error avoid "Can only use lower 16 bits for requestCode".

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Luciano Marqueto
  • 1,148
  • 1
  • 15
  • 24
16

I was also facing the same problem once I shifted this block of code outside of a Fragment to a Utility Class, with parentActivity passed as argument,

Intent intent = new Intent(parentActivity, CameraCaptureActivity.class);
parentActivity.startActivityForResult(intent,requestCode);

Then I was not getting any value in onActivityResult method of that Fragment, Afterwards, I changed the argument to Fragment, so the revised definition of method looked like,

Intent intent = new Intent(fragment.getContext(), CameraCaptureActivity.class);
fragment.startActivityForResult(intent,requestCode);

After that, I was able to get value in onActivityResult on the Fragment

Shamsul Arefin
  • 1,771
  • 1
  • 21
  • 21
15

Kotlin version for those who use Android Navigation Component inspired in Mohit Mehta's answer

 override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
    super.onActivityResult(requestCode, resultCode, data)
    supportFragmentManager.primaryNavigationFragment?.childFragmentManager?.fragments?.forEach { fragment ->
        fragment.onActivityResult(requestCode, resultCode, data)
    }
}
  • 1
    This is the correct code override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) { super.onActivityResult(requestCode, resultCode, data) activity?.supportFragmentManager?.primaryNavigationFragment?. childFragmentManager?.fragments?.forEach { fragment -> fragment.onActivityResult(requestCode, resultCode, data) } } – Felipe Franco Aug 21 '20 at 21:00
  • 2
    Working for Kotlin Navigation Component – Chirag Savsani Aug 28 '20 at 13:08
  • Should I write code (for example if(resultCode != Result_ok)) inside forEach scope or inside the main scope after the forEach scope ? – Abdulsamet Kılınçarslan May 11 '21 at 12:08
  • It solved my problem , Nav graph fragment onActivityResult . WellDone – Hossein Kurd Jul 11 '21 at 07:12
14

I can add two advices if someone still cannot make it. In Manifest.xml file, make sure the hosting activity didn't finish when call back and the activity to be started has the launch mode as standard. See details as below:

For Hosting activity, set the no history property as false if have

android:noHistory="false"

For Activity to be started, set the launch mode as standard if have

android:launchMode="standard"
jowett
  • 774
  • 5
  • 10
11

FOR NESTED FRAGMENTS (for example, when using a ViewPager)

In your main activity:

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

In your main top level fragment(ViewPager fragment):

@Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
    YourFragment frag = (YourFragment) getChildFragmentManager().getFragments().get(viewPager.getCurrentItem());
    frag.yourMethod(data);  // Method for callback in YourFragment
    super.onActivityResult(requestCode, resultCode, data);
}

In YourFragment (nested fragment):

public void yourMethod(Intent data){
    // Do whatever you want with your data
}
Community
  • 1
  • 1
Jyotman Singh
  • 10,792
  • 8
  • 39
  • 55
10

I also met this problem in a Fragment. And I called startActivityForResult in a DialogFragment.

But now this problem has been resolved:
FragmentClassname.this.startActivityForResult.

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Courysky
  • 331
  • 4
  • 4
  • Great, worked for me, because I was calling `startActivityForResult(...)` from an abstract class inside the fragment's code. – Vince Jul 19 '15 at 01:08
8

In my case it was an Android bug (http://technet.weblineindia.com/mobile/onactivityresult-not-getting-called-in-nested-fragments-android/), if you use supported FragmentActivity you have to use getSupportFragmentManager instead of getChildFragmentManager:

List<Fragment> fragments = getSupportFragmentManager().getFragments();
if (fragments != null) {
    for (Fragment fragment : fragments) {
        if(fragment instanceof UserProfileFragment) {
            fragment.onActivityResult(requestCode, resultCode, data);
        }
    }
}
Piyush
  • 18,895
  • 5
  • 32
  • 63
Nammen8
  • 619
  • 1
  • 11
  • 31
7

In short,

In fragment, declare Fragment fragment = this;

after that use fragment.startActivityForResult.

The result will return in activityResult.

Graham Savage
  • 1,129
  • 13
  • 20
Clevester
  • 169
  • 1
  • 4
7

Inside your fragment, call

this.startActivityForResult(intent, REQUEST_CODE);

where this is referring to the fragment. Otherwise do as @Clevester said:

Fragment fragment = this;
....
fragment.startActivityForResult(intent, REQUEST_CODE);

I also had to call

super.onActivityResult(requestCode, resultCode, data);

in the parent activity's onActivityResult to make it work.

(I adapted this answer from @Clevester's answer.)

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Suragch
  • 484,302
  • 314
  • 1,365
  • 1,393
  • In my fragment prefixing it with `this` as in `this.startActivityForResult(...)` is what triggered the callback. Thanks! – Lance Samaria Jun 13 '23 at 08:14
6

Solution 1:

Call startActivityForResult(intent, REQUEST_CODE); instead of getActivity().startActivityForResult(intent, REQUEST_CODE);.

Solution 2:

When startActivityForResult(intent, REQUEST_CODE); is called the activity's onActivityResult(requestCode,resultcode,intent) is invoked, and then you can call fragments onActivityResult() from here, passing the requestCode, resultCode and intent.

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Amey Haldankar
  • 2,223
  • 1
  • 24
  • 22
6

With Android's Navigation component, this problem, when you have nested Fragments, could feel like an unsolvable mystery.

Based on knowledge and inspiration from the following answers in this post, I managed to make up a simple solution that works:

In your activity's onActivityResult(), you can loop through the active Fragments list that you get using the FragmentManager's getFragments() method.

Please note that for you to do this, you need to be using the getSupportFragmentManager() or targeting API 26 and above.

The idea here is to loop through the list checking the instance type of each Fragment in the list, using instanceof.

While looping through this list of type Fragment is ideal, unfortunately, when you're using the Android Navigation Component, the list will only have one item, i.e. NavHostFragment.

So now what? We need to get Fragments known to the NavHostFragment. NavHostFragment in itself is a Fragment. So using getChildFragmentManager().getFragments(), we once again get a List<Fragment> of Fragments known to our NavHostFragment. We loop through that list checking the instanceof each Fragment.

Once we find our Fragment of interest in the list, we call its onActivityResult(), passing to it all the parameters that the Activity's onActivityResult() declares.

//  Your activity's onActivityResult()

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

        List<Fragment> lsActiveFragments = getSupportFragmentManager().getFragments();
        for (Fragment fragmentActive : lsActiveFragments) {

            if (fragmentActive instanceof NavHostFragment) {

                List<Fragment> lsActiveSubFragments = fragmentActive.getChildFragmentManager().getFragments();
                for (Fragment fragmentActiveSub : lsActiveSubFragments) {

                    if (fragmentActiveSub instanceof FragWeAreInterestedIn) {
                        fragmentActiveSub.onActivityResult(requestCode, resultCode, data);
                    }

                }

            }

        }

    }
Edward Quixote
  • 350
  • 5
  • 16
4

Most of these answers keep saying that you have to call super.onActivityResult(...) in your host Activity for your Fragment. But that did not seem to be working for me.

So, in your host Activity you should call your Fragments onActivityResult(...) instead. Here is an example.

public class HostActivity extends Activity {

    private MyFragment myFragment;

    protected void onActivityResult(...) {
        super.onActivityResult(...);
        this.myFragment.onActivityResult(...);
    }
}

At some point in your HostActivity you will need to assign this.myFragment the Fragment you are using. Or, use the FragmentManager to get the Fragment instead of keeping a reference to it in your HostActivity. Also, check for null before you try to call the this.myFragment.onActivityResult(...);.

prolink007
  • 33,872
  • 24
  • 117
  • 185
4

Another use case not already described in other answers:

onActivityResult() declared in fragment is not invoked when using exception.startResolutionForResult():

if (exception is ResolvableApiException) {
    exception.startResolutionForResult(activity!!, MY_REQUEST_CODE)
}

In this case replace exception.startResolutionForResult() with fragment's startIntentSenderForResult():

if (exception is ResolvableApiException) {
    startIntentSenderForResult(exception.resolution.intentSender, MY_REQUEST_CODE, null, 0, 0, 0, null)
}
dominik
  • 2,404
  • 2
  • 29
  • 33
3
public class takeimage extends Fragment {

    private Uri mImageCaptureUri;
    private static final int PICK_FROM_CAMERA = 1;
    private static final int PICK_FROM_FILE = 2;
    private String mPath;
    private ImageView mImageView;
    Bitmap bitmap = null;
    View view;

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
        view = inflater.inflate(R.layout.activity_send_image, container, false);
        final String[] items = new String[] { "From Camera", "From SD Card" };
        mImageView = (ImageView)view.findViewById(R.id.iv_pic);
        ArrayAdapter<String> adapter = new ArrayAdapter<String>(getActivity(), android.R.layout.select_dialog_item, items);
        AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
        builder.setTitle("Select Image");

        builder.setAdapter(adapter, new DialogInterface.OnClickListener() {
            public void onClick(DialogInterface dialog, int item) {
                if (item == 0) {
                    Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
                    File file = new File(Environment.getExternalStorageDirectory(), "tmp_avatar_"
                        + String.valueOf(System.currentTimeMillis())
                        + ".jpg");
                    mImageCaptureUri = Uri.fromFile(file);

                    try {
                        intent.putExtra(
                            android.provider.MediaStore.EXTRA_OUTPUT,
                            mImageCaptureUri);
                        intent.putExtra("return-data", true);

                        getActivity().startActivityForResult(intent,
                            PICK_FROM_CAMERA);
                    } catch (Exception e) {
                        e.printStackTrace();
                    }

                    dialog.cancel();
                } else {
                    Intent intent = new Intent();

                    intent.setType("image/*");
                    intent.setAction(Intent.ACTION_GET_CONTENT);

                    getActivity().startActivityForResult(
                        Intent.createChooser(intent,
                            "Complete action using"), PICK_FROM_FILE);
                }
            }
        });
        final AlertDialog dialog = builder.create();

        Button show = (Button) view.findViewById(R.id.btn_choose);
        show.setOnClickListener(new OnClickListener() {
            @Override
            public void onClick(View v) {
                // Switch the tab content to display the list view.
                dialog.show();
            }
        });

    return view;
    }

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

        if (resultCode != Activity.RESULT_OK)
            return;

        if (requestCode == PICK_FROM_FILE) {
            mImageCaptureUri = data.getData();
            // mPath = getRealPathFromURI(mImageCaptureUri); //from Gallery

            if (mPath == null)
                mPath = mImageCaptureUri.getPath(); // from File Manager

            if (mPath != null)
                bitmap = BitmapFactory.decodeFile(mPath);
        } else {
            mPath = mImageCaptureUri.getPath();
            bitmap = BitmapFactory.decodeFile(mPath);
        }
        mImageView.setImageBitmap(bitmap);  
    }

    public String getRealPathFromURI(Uri contentUri) {
        String [] proj = {MediaStore.Images.Media.DATA};
        Cursor cursor = managedQuery(contentUri, proj, null, null,null);

        if (cursor == null) return null;

        int column_index = cursor.getColumnIndexOrThrow(MediaStore.Images.Media.DATA);
        cursor.moveToFirst();
        return cursor.getString(column_index);
    }
} 
Ken Herbert
  • 5,205
  • 5
  • 28
  • 37
3
  1. You can simply override BaseActivity onActivityResult on fragment baseActivity.startActivityForResult .

  2. On BaseActivity add interface and override onActivityResult.

    private OnBaseActivityResult baseActivityResult;
    public static final int BASE_RESULT_RCODE = 111;
    public interface OnBaseActivityResult{
        void onBaseActivityResult(int requestCode, int resultCode, Intent data);
       }
    }
    
    @Override
    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
    super.onActivityResult(requestCode, resultCode, data);
    if(getBaseActivityResult() !=null && requestCode == BASE_RESULT_RCODE){
        getBaseActivityResult().onBaseActivityResult(requestCode, resultCode, data);
        setBaseActivityResult(null);
    }
    
  3. On Fragment implements OnBaseActivityResult

    @Override
    public void onBaseActivityResult(int requestCode, int resultCode, Intent data) {
    Log.d("RQ","OnBaseActivityResult");
    if (data != null) {
        Log.d("RQ","OnBaseActivityResult + Data");
        Bundle arguments = data.getExtras();
      }
    }
    

This workaround will do the trick.

Khaled Lela
  • 7,831
  • 6
  • 45
  • 73
3

If the above problem is faced at Facebook login then you can use the below code in a parent activity of your fragment like:

Fragment fragment = getFragmentManager().findFragmentById(android.R.id.tabcontent);
fragment.onActivityResult(requestCode, resultCode, data);

Or:

Fragment fragment = getFragmentManager().findFragmentById("fragment id here");
fragment.onActivityResult(requestCode, resultCode, data);

And add the below call in your fragment...

callbackManager.onActivityResult(requestCode, resultCode, data);
Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Ketan Patel
  • 2,155
  • 19
  • 27
3

Kotlin version (In your activity onActivityResult())

 override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
    //add following lines in your activity
    if(supportFragmentManager?.fragments!=null && supportFragmentManager?.fragments!!.size>0)
     for (i in 0..supportFragmentManager?.fragments!!.size-1) {
         val fragment= supportFragmentManager?.fragments!!.get(i)
         fragment.onActivityResult(requestCode, resultCode, data)
    }
 }
Ranjithkumar
  • 16,071
  • 12
  • 120
  • 159
3

With getting help from @Mohit Mehta if you are using Navigation Component this may help you as well. It Worked For me..

In the onActivityResult method of MainActivity paste below code:

for (Fragment fragment : navHostFragment.getChildFragmentManager().getFragments()){
        if (fragment != null){
            Log.d(TAG, "onResult Has Been Sent!");
            fragment.onActivityResult(requestCode, resultCode, data);
        }
    }

and in onActivityResult method of YOUR FRAGMENT you can get the result. Hope this helps you.

StackOverflower
  • 369
  • 2
  • 12
3

ADD this

public void onClick(View v) {   
    Intent intent = new Intent(Intent.ACTION_GET_CONTENT,MediaStore.Images.Media.EXTERNAL_CONTENT_URI);
        startActivityForResult(intent, 1);
}

when you will replace your code with this above code then automatically your this

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

Method will Start working

//No Need to write this code in onclick method
    Intent intent=new Intent();
    intent.setType("image/*");
    intent.setAction(Intent.ACTION_GET_CONTENT)
    startActivityForResult(intent,1);
    Toast.makeText(getContext(), "image"+intent, Toast.LENGTH_SHORT).show();
Bytecode
  • 6,551
  • 16
  • 54
  • 101
2

first of all you need to override this code in Activity;

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

and after, in your fragment,

startActivityForResult(intent,GALLERY_REQUEST_CODE);

and again than in your fragment,

@Override
public void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) {
    super.onActivityResult(requestCode, resultCode, data);
    // Result code is RESULT_OK only if the user selects an Image
    if (resultCode == Activity.RESULT_OK) {

    }

}
ozanurkan
  • 399
  • 4
  • 13
1

As Ollie C mentioned, there is an active bug for the support library using returned values to onActivityResult when you are using nested fragments. I just hit it :-(.

See Fragment.onActivityResult not called when requestCode != 0.

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
chaqke
  • 1,497
  • 17
  • 23
1

I have a strong suspicion that all of the answers here are nothing more than hacks. I've tried them all and many others, but without any reliable conclusion as there is always some sort of stupid issue. I for one cannot rely on inconsistent results. If you look at the official Android API documentation for Fragments you will see Google clearly states the following:

Call startActivityForResult(Intent, int) from the fragment's containing Activity.

See: Android Fragment API

So, it would seem that the most correct and reliable approach would be to actually call startActivityForResult() from the hosting activity and also handle the resulting onActivityResult() from there.

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Chris
  • 4,593
  • 1
  • 33
  • 37
  • 2
    I dont think "call startActivityForResult from Activity" is a recommendation. If you look at the implementation inside Fragment base class, then all it does is `mActivity.startActivityFromFragment(this, intent, requestCode)` - so it is nothing else but a convenience wrapper – Anti Veeranna Oct 02 '14 at 07:01
1

Your code has a nested fragment. Calling super.onActivityForResult doesn't work

You don't want to modify every activity that your fragment can be called from and or make a work around calling every fragment in the fragment chain.

Here is one of many working solutions. create a fragment on the fly and wire it directly to the activity with the support fragment manager. Then call startActivityForResult from the newly created fragment.

private void get_UserEmail() {

    if (view == null) {
        return;
    }
    ((TextView) view.findViewById(R.id.tvApplicationUserName))
            .setText("Searching device for user accounts...");

    final FragmentManager fragManager = getActivity().getSupportFragmentManager();

    Fragment f = new Fragment() {
        @Override
        public void onAttach(Activity activity) {
            super.onAttach(activity);
            startActivityForResult(AccountPicker.newChooseAccountIntent(null, null,
                    new String[]{"com.google"}, false, null, null, null, null), REQUEST_CODE_PICK_ACCOUNT);
        }

        @Override
        public void onActivityResult(int requestCode, int resultCode,
                                     Intent data) {
            if (requestCode == REQUEST_CODE_PICK_ACCOUNT) {
                String mEmail = "";
                if (resultCode == Activity.RESULT_OK) {
                    if (data.hasExtra(AccountManager.KEY_ACCOUNT_NAME)) {
                        mEmail = data
                                .getStringExtra(AccountManager.KEY_ACCOUNT_NAME);
                    }
                }
                if (mActivity != null) {
                    GoPreferences.putString(mActivity, SettingApplication.USER_EMAIL, mEmail);
                }
                doUser();
            }
            super.onActivityResult(requestCode, resultCode, data);
            fragManager.beginTransaction().remove(this).commit();
        }
    };
    FragmentTransaction fragmentTransaction = fragManager
            .beginTransaction();
    fragmentTransaction.add(f, "xx" + REQUEST_CODE_PICK_ACCOUNT);
    fragmentTransaction.commit();
}
danny117
  • 5,581
  • 1
  • 26
  • 35
  • This actually works and I've only got one vote for it. Create a fragment on the fly. Too easy but its true working solution. Someone even tried to edit it for me. – danny117 Jun 14 '16 at 13:18
1

If you are using nested fragments, this is also working:

getParentFragment().startActivityForResult(intent, RequestCode);

In addition to this, you have to call super.onActivityResult from parent activity and fill the onActivityResult method of the fragment.

Piyush
  • 18,895
  • 5
  • 32
  • 63
Oguz Ozcan
  • 1,694
  • 19
  • 26
1

My Problem was with the Host activity I found it with a set android:launchMode="standard" I removed it temporary an it work !

TooCool
  • 10,598
  • 15
  • 60
  • 85
1

One point no one has mention that make sure your Host Activity launch mode must not set to singleInstance or singleTask.

onActivityResult will not work if your launch mode set to SingleInstance or SingleTask. or you call your activity using these IntentFilters

standard or singleTop launch mode will work fine.

marc_s
  • 732,580
  • 175
  • 1,330
  • 1,459
Zar E Ahmer
  • 33,936
  • 20
  • 234
  • 300
1

In my case, in developer options I have turned on "Do not keep activities", which was causing this issue.

In case it helps someone.

Monster Brain
  • 1,950
  • 18
  • 28
0

I just make a workaround method:

public static Fragment _tempFragment = null;
@Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
    super.onActivityResult(requestCode, resultCode, data);
    if(_tempFragment != null)
        _tempFragment.onActivityResult(requestCode, resultCode, data);
}

In your Fragment, before startActivityResult, set

MainActivity._tempFragment = this;

After onActivityResult <-- in Fragment

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

     // Do your job
     {

     }
     MainActivity._tempFragment = null;
}
Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Ah Lam
  • 167
  • 1
  • 2
  • 8
0

Simply use the below code for the fragment.

@Override
public void onOtherButtonClick(ActionSheet actionSheet, int index) {

    if (index == 1)
    {
        Intent intent = new Intent(Intent.ACTION_PICK,
                                   android.provider.MediaStore.Images.Media.EXTERNAL_CONTENT_URI);
        intent.setType("image/*");
        startActivityForResult(Intent.createChooser(intent,
                                                    "Select Picture"), 1);
     }
}

public void onActivityResult(int requestCode, int resultCode, Intent data) {
    super.onActivityResult(requestCode, resultCode, data);
    if (resultCode == 1) {
        if (requestCode == 1) {
            Uri selectedImageUri = data.getData();
            //selectedImagePath = getPath(selectedImageUri);
        }
    }
}

onActivityResult will call without calling its parent.

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Kirtikumar A.
  • 4,140
  • 43
  • 43
0

If there is trouble with the method onActivityResult that is inside the fragment class, and you want to update something that's is also inside the fragment class, use:

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

    if(resultCode == Activity.RESULT_OK)
    {
        // If the user had agreed to enabling Bluetooth,
        // populate the ListView with all the paired devices.
        this.arrayDevice = new ArrayAdapter<String>(this.getContext(), R.layout.device_item);
        for(BluetoothDevice bd : this.btService.btAdapater.getBondedDevices())
        {
            this.arrayDevice.add(bd.getAddress());
            this.btDeviceList.setAdapter(this.arrayDevice);
        }
    }
    super.onActivityResult(requestCode, resultCode, data);
}

Just add the this.variable as shown in the code above. Otherwise the method will be called within the parent activity and the variable will not updated of the current instance.

I tested it also by putting this block of code into the MainActivity, replacing this with the HomeFragment class and having the variables static. I got results as I expected.

So if you want to have the fragment class having its own implementation of onActivityResult, the code example above is the answer.

Piyush
  • 18,895
  • 5
  • 32
  • 63
Evgeny Danilenko
  • 181
  • 2
  • 10
0

One of the simplest way is to start an activity from your fragment.

startActivity(ActivityName);

Then, add you call startActivityForResult(intent,"1"); from your Activity and add onActivityResult in your activity

startActivityForResult(intent,"1");

@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
    Fragment fragment = getSupportFragmentManager().findFragmentById(R.id.dualPane);
    fragment.onActivityResult(requestCode, resultCode, data);
// perform other activity result like fetching from Uris or handling cursors

finish(); // finish the activity will  get to back to your fragment.
}
Rohit Goyal
  • 550
  • 8
  • 9
0

onActivityResult is deprecated now. You can use follow code:

   registerForActivityResult(ActivityResultContracts.StartActivityForResult()){ result->
    // here you can handle result, result.data and result.resultCode
   }

For start activity

    val intent = Intent(android.provider.MediaStore.ACTION_IMAGE_CAPTURE)
    launcher.launch(intent)
-7

Just simply call:

startActivityForResult(intent, "1");
Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131