Reputation: 40002
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);
}
}
Upvotes: 994
Views: 511182
Reputation: 437
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.
Upvotes: 3
Reputation: 91
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)
Upvotes: 0
Reputation: 7472
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)
}
}
Upvotes: 118
Reputation: 6591
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();
Upvotes: 3
Reputation: 2119
In my case, in developer options I have turned on "Do not keep activities", which was causing this issue.
In case it helps someone.
Upvotes: 1
Reputation: 2515
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)
}
}
Upvotes: 16
Reputation: 360
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);
}
}
}
}
}
Upvotes: 6
Reputation: 1285
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);
}
}
Upvotes: 24
Reputation: 419
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) {
}
}
Upvotes: 2
Reputation: 18386
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)
}
}
Upvotes: 3
Reputation: 2761
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)
}
Upvotes: 4
Reputation: 1917
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
Upvotes: 16
Reputation: 6480
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
}
Upvotes: 320
Reputation: 40002
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.
Upvotes: 1355
Reputation: 7592
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);
}
}
Upvotes: 86
Reputation: 629
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);
}
}
}
Upvotes: 8
Reputation: 1714
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.
Upvotes: 1
Reputation: 181
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.
Upvotes: 0
Reputation: 34360
One point no one has
mention
that make sure your Host Activity launch mode must not set tosingleInstance
orsingleTask
.
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.
Upvotes: 1
Reputation: 10815
My Problem was with the Host activity I found it with a set android:launchMode="standard"
I removed it temporary an it work !
Upvotes: 1
Reputation: 5651
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();
}
Upvotes: 1
Reputation: 1198
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".
Upvotes: 18
Reputation: 11330
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
}
Upvotes: 11
Reputation: 2215
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);
Upvotes: 3
Reputation: 4204
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.
Upvotes: 0
Reputation: 331
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
.
Upvotes: 10
Reputation: 511726
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.)
Upvotes: 7
Reputation: 2243
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
.
Upvotes: 6
Reputation: 4593
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.
Upvotes: 1