getActivity() in fragment is null after orientation change - android

I have a problem with startActivityForResult, fragments and orientation changes.
I call startActivityForResult() from one fragment, then I open second activity with fragment attached. In this second activity when I change orientation and go back to the first activity then onActivityResult (fragment method) is called. But there's a problem, because a I have something like this:
public void onActivityResult(int requestCode, int resultCode, Intent data) {
getActivity(); //here's a problem because
//getActivity is null but only after orientation change on second activity
}

You will need to call the required super before calling getActivity(), like so:
#Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
getActivity();
}

This solved for me:
private Activity activity;
#Override
public void onActivityCreated(#Nullable Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
this.activity = getActivity();
}
and use this activity anywhere in the fragment that you need.

All the problem was that I don't declare android:id for the fragment in XML. Android need's ID or TAG to recognize stored fragment and reproduce all element's in it. So guys, remeber - every instance of fragment need unique id or tag!

Related

Handling the Payumoney Response in a Fragment

I have init the payumoney flow from a fragment and I am getting the response OnActivityResult in my Activity. but I need to update some values the after the response in fragment. there is any possible to get the response in fragment or get my custom objects from fragment to activity while getting response?
Thanks in advance.
You can do it 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.
Option 2:
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
}
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
}

Get onActivityResult show on Fragment [duplicate]

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);
}
}
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.
I think you called getActivity().startActivityForResult(intent,111);. You should call startActivityForResult(intent,111);.
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
}
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)
}
}
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);
}
}
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:
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.
How do we resolve this issue? There is common workaround solution in this post.
GitHub: https://github.com/shamanland/nested-fragment-issue
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.
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);
}
}
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".
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
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)
}
}
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"
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
}
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.
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);
}
}
}
In short,
In fragment, declare Fragment fragment = this;
after that use fragment.startActivityForResult.
The result will return in activityResult.
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.
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.)
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:
Answer in this post
Answer in this post
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);
}
}
}
}
}
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(...);.
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)
}
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);
}
}
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.
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);
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)
}
}
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();
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) {
}
}
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.
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.
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.

OnPlaceSelectedListener of SupportPlaceAutocompleteFragment not fired inside ViewPager

My application has and activity with a viewPager and 4 fragments.
In one fragment I added a google SupportPlaceAutocompleteFragment and
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.area_swipe_fragment, container, false);
SupportPlaceAutocompleteFragment autocompleteFragment = (SupportPlaceAutocompleteFragment)
getChildFragmentManager().findFragmentById(R.id.place_autocomplete_fragment);
autocompleteFragment.setOnPlaceSelectedListener(new PlaceSelectionListener() {
#Override
public void onPlaceSelected(Place place) {
Toast.makeText(ctx, "do something", Toast.LENGTH_SHORT).show();
}
#Override
public void onError(Status status) {
}
});
return view;
}
My problem is the onPlaceSelectedListener is never fired and I can't get the result of the selected place. Instead get fired the onActivityResults() placed in the second fragment.
I tried with a onActivityResults() in the first fragment but it doesn't get fired, always executed the one in the second fragment.
Any ideas?
From the docs:
If your fragment is nested within another fragment, your app must also
forward onActivityResult() calls to the containing fragment, as shown
in the following snippet:
#Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
autocompleteFragment.onActivityResult(requestCode, resultCode, data);
}
Perhaps this is the solution.
The #AndrewR answer took me on the right track, very similar to the comments, I override onActivityResult however it didn't work.
The problem was the host Activity wasn't calling the super:
public class HostActivity extends AppCompatActivity {
//Please don't forget other relevant methods
#Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
//super.onActivityResult... is the important line
//Add other custom behaviours
}
}
Assuming the Google Places API for android services are properly enabled for your api key, even I observed similar issue using SupportPlaceAutocompleteFragment, where the onPlaceSelected is never getting triggered on place selection. However later when i tried with the intent approach, things worked..
I ran into this issue this morning, and after a bunch of reading and random similar issues I got the following to work.
If you look at the source code for SupportPlaceAutocompleteFragment you will see it calls
public class SupportPlaceAutocompleteFragment extends Fragment {
private void zzzG() {
...
try {
Intent var2 = (new IntentBuilder(2)).setBoundsBias(this.zzaRk).setFilter(this.zzaRl).zzeq(this.zzaRj.getText().toString()).zzig(1).build(this.getActivity());
this.startActivityForResult(var2, 1);
}
...
}
public void onActivityResult(int requestCode, int resultCode, Intent data) {
if(requestCode == 1) {
...
}
super.onActivityResult(requestCode, resultCode, data);
}
}
Depending on your integration this can cause the RequestCode to change to something other than 1. By extending it to override the startActivityForResult you can change the behaviour by calling getActivity().startActivityForResult instead of this.startActivityForResult
public class WrappedSupportPlaceAutocompleteFragment extends SupportPlaceAutocompleteFragment {
#Override
public void startActivityForResult(Intent intent, int requestCode) {
this.getActivity().startActivityForResult(intent, requestCode);
}
}
from there you can now follow what AndrewR mentioned and pass the activity result from the activity to the fragment and get the expected result.

How to update tab fragment inside a Fragment from base activity in Android?

Initially we had activity for our app,on that we have return value from activity to activity using onActivityResult.
But now we are changing into fragment,but we are not getting the return value between fragment.
Is there is any solution for onActivityResult between fragment.
yes there is a solution:
on your activity: Don't do anything. If you for some reason absolutely needs to, you must always call super like following.
#Override protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
}
then, your Fragments, you call:
public void doSomethingThatNeedsActivityResult(){
startActivityForResult(intent, YOUR_FRAG_REQUEST_CODE)
}
#Override
public void onActivityResult (int requestCode, int resultCode, Intent data){
if(requestCode == YOUR_FRAG_REQUEST_CODE){
// here the result
}
}
important to notice is that you should not call getActivity().startActivityForResult(...) it must be called using the fragment specific method.

onActivityResult never invoked within Activity part of ActivityGroup

I'm using a TabActivity that calls an ActivityGroup. Tipical approach that brings problems.
Now I'm facing a problem with onActivityResult
in my Activity I have..
public class MyActivity extends Activity {
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.place_buttontab_community_media);
Button ButtonClick =(Button) findViewById(R.id.addPicture);
ButtonClick.setOnClickListener(new OnClickListener (){
#Override
public void onClick(View view)
{
Intent cameraIntent = new Intent(android.provider.MediaStore.ACTION_IMAGE_CAPTURE);
// request code
startActivityForResult(cameraIntent, CAMERA_PIC_REQUEST);
}
});
}
#Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
Log.i(TAG, "hi");
super.onActivityResult(requestCode, resultCode, data);
}
}
unfortunately onActivityResult is never invoked.
You should listen for the result in the ActivityGroup's onActivityResult(). When a result is received, you have to decide which Activity should receive it and call it's onActivityResult() method with the received values.
I recently encountered this, to consolidate Andras' and virtual82's answer and discussion above (Sorry I can't add comment due to my low rep):
If your activity is started inside an ActivityGroup, which is used by TabActivity for example, then only the ActivityGroup activity can receive method calls to onActivityResult when you start an activity with startActivityForResult(Intent intent, int requestCode) from an activity inside the ActivityGroup.
In my situation, I have a TabActivity that contains FragmentActivitys. A Fragment inside a FragmentActivity may start an activity for result.
In this case the Fragment needs to start the activity with TabActivity as the calling activity:
Intent doSomethingIntent = new Intent();
//getActivity() returns the FragmentActivity, so we need to get the TabActivity with getParent()
Activity tabActivity = getActivity().getParent();
doSomethingIntent .setClass(tabActivity , PostCommentActivity.class);
tabActivity.startActivityForResult(doSomethingIntent , DO_SOMETHING_REQ_CODE);
Then in onActivityResult of the TabActivity, pass the result back to the Fragment.
Activity currentActivity = getLocalActivityManager().getCurrentActivity();
//get the FragmentActivity in order to get the Fragment instance
if(currentActivity instanceof FragmentActivity){
FragmentActivity currentFragmentActivity = (FragmentActivity)currentActivity ;
//R.id.l_container is the layout/viewgroup that contains the Fragment
Fragment currentFragment = currentFragmentActivity.getSupportFragmentManager().findFragmentById(R.id.l_container);
if(currentFragment != null){
//pass result to the Fragment!
frag.onActivityResult(requestCode, resultCode, data);
}
}
I realize that ActivityGroup, TabActivity and LocalActivityManager are deprecated in favor of Fragment and FragmentManager, but my project time constraint didn't allow me enough time to fully upgrade.
Hopefully this post will help someone in this situation, instead of the usual "don't do it" kind of response you see else where.

Categories

Resources