The activity hosting this fragment has its onActivityResult
called when the camera activity returns.
My fragment starts an activity for a result with th
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)
}
}
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);
}
}
}
}
}
You can simply override BaseActivity onActivityResult
on fragment baseActivity.startActivityForResult
.
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);
}
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.
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);
}
}
My Problem was with the Host activity I found it with a set android:launchMode="standard"
I removed it temporary an it work !
This is one of the most popular issue. We can found lots of thread regarding this issue. But none of them is useful for ME.
So I have solved this problem using this solution.
Let's first understand why this is happening.
We can call startActivityForResult
directly from Fragment but actually mechanic behind are all handled by Activity.
Once you call startActivityForResult
from a Fragment, requestCode will be changed to attach Fragment's identity to the code. That will let Activity be able to track back that who send this request once result is received.
Once Activity was navigated back, the result will be sent to Activity's onActivityResult with the modified requestCode which will be decoded to original requestCode + Fragment's identity. After that, Activity will send the Activity Result to that Fragment through onActivityResult. And it's all done.
The problem is:
Activity could send the result to only the Fragment that has been attached directly to Activity but not the nested one. That's the reason why onActivityResult of nested fragment would never been called no matter what.
Solution:
1) Start Intent in your Fragment by below code:
/** Pass your fragment reference **/
frag.startActivityForResult(intent, REQUEST_CODE); // REQUEST_CODE = 12345
2) Now in your Parent Activity override **onActivityResult()
:**
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
}
You have to call this in parent activity to make it work.
3) In your fragment call:
@Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if (resultCode == Activity.RESULT_OK) {
}
}
That's it. With this solution, it could be applied for any single fragment whether it is nested or not. And yes, it also covers all the case! Moreover, the codes are also nice and clean.