resultCode 0 and data zero in onActivityResult - android

I have activity with one fragment, and then that fragment call some activity which that activity will give some value into first activity. i use onActivityResult but i don't know why resultCode always 0 and data always zero,.
on Activity One i have
#Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
Log.d(TAG, "onActivityResult: "+ requestCode +" "+resultCode+" "+data);
}
Activity one have some fragmentX which call activity two
private final int REQUEST_CODE = 10;
private void start (){
Intent intent = new Intent(getContext(),Main2Activity.class);
intent.putExtra("xxx","test1");
getActivity().startActivityForResult(intent,REQUEST_CODE);
}
then in Activity Two, when i touch onBackpress, will pass some value.
public class Main2Activity extends AppCompatActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main2);
}
#Override
public void onBackPressed() {
super.onBackPressed();
Intent intent = getIntent().putExtra("yyy","test2");
setResult(RESULT_OK,intent);
}
}
but, i don't know why, onActivityResult i can't get the data.
my final purpose is, i want to setArgument that data to fragmentX.

1.You can call onActivityResult in the fragment
#Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
Log.d(TAG, "onActivityResult: "+ requestCode +" "+resultCode+" "+data);
}
2.Use super.onBackPressed(); after setResult in your method
#Override
public void onBackPressed() {
Intent intent = getIntent().putExtra("yyy","test2");
setResult(RESULT_OK,intent);
super.onBackPressed();
}

In first activity write the below code:
1st method:
#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);
}
}
In Fragment
#Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
// In fragment write your logic here
}
2nd method: (I didn't try but as per doc may be this is one of the reason try once) if it will not work go 1st method its 100 percent solution
Here when your calling second activity using getContext()
getContext() - Returns the context view only current running activity.
getActivity()- Return the Activity this fragment is currently associated with.
Try instead of getContext() use getActivity() when you calling intent to next activity
Ex:
private final int REQUEST_CODE = 10;
Intent intent = new Intent(getActivity(),Main2Activity.class);
intent.putExtra("xxx","test1");
getActivity().startActivityForResult(intent,REQUEST_CODE);

For start new activity
private final int REQUEST_CODE = 10;
private void start (){
Intent intent = new Intent(getContext(),Main2Activity.class);
intent.putExtra("xxx","test1");
getActivity().startActivityForResult(intent,REQUEST_CODE);
}
From Second activity
public class Main2Activity extends AppCompatActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main2);
}
#Override
public void onBackPressed() {
super.onBackPressed();
Intent intent = getIntent().putExtra("yyy","test2");
setResult(10,intent);
}
}
you have to set the integer code using which you have started second activity. you have started second activity with the code "10".so use the same value when you setResult(10,intent);
onActivityResult you need to check Request code
#Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if(requestCode==10){
if(data!=null)
{
//you have to manage your own list of fragments for activity because getSupportFragmentManager().getFragments() is deprecated now.
//Send data to fragments
if (arrayFragments != null) {
for (Fragment fragment : arrayFragments) {
fragment.onActivityResult(requestCode, resultCode, data);
}
}
}
}
}
Remember you have to manage your own list of fragments using ArrayList or HashMap.
Hope this will help you if you need any other help inform me.

if you wants to send return data in onActivityResult then you should use super.onBackPressed() after data set in setResult() method
example:
#Override
public void onBackPressed() {
val intent = Intent()
intent.putExtra("IsReturnData", true)
setResult(RESULT_OK,intent);
super.onBackPressed(); //write this line at the end of method
}

Related

onActivityResult from Activity to Fragment

I have a problem regarding onActivityResult. First, I opened the Add New Message Fragment to select the image. When I select the image, it doesn't return the result to my current fragment. I put onActivityResult in both my MainActivity and AddMessageFragment but it doesn't call the result in my fragment. My MainActivity is used to set up the Navigation Controller. I use Matisse library for my image picker. Can someone please help me with me? Been stuck for the whole day with this issue.
MainActivity
#Override
public void onActivityResult(int requestCode, int resultCode, Intent data)
{
super.onActivityResult(requestCode, resultCode, data);
}
AddMessageFragment
#OnClick({R.id.addImage})
public void openGallery()
{
permission.addOnStorageListener(new Permission.OnStorageSuccess()
{
#Override
public void OnStorageSuccess()
{
permission.requestCamera();
}
});
permission.addOnCameraListener(new Permission.OnCameraSuccess()
{
#Override
public void OnCameraSuccess()
{
Matisse.from(getActivity())
.choose(MimeType.of(MimeType.JPEG, MimeType.PNG))
.countable(false)
.capture(true)
.captureStrategy(new CaptureStrategy(true, "com.gprop.users.fileprovider"))
.maxSelectable(1)
.restrictOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT)
.thumbnailScale(0.85f)
.imageEngine(new Glide4Engine())
.originalEnable(false)
.forResult(99);
}
});
permission.requestStorage();
}
#Override
public void onActivityResult(int requestCode, int resultCode, Intent data)
{
super.onActivityResult(requestCode, resultCode, data);
if(requestCode == 99 && resultCode == Main.RESULT_OK)
{
mSelected = Matisse.obtainPathResult(data);
if(mSelected.size() > 0)
{
Glide.with(this).load(mSelected.get(0)).into(addImage);
Luban.compress(new File(mSelected.get(0)), getActivity().getFilesDir())
.putGear(Luban.THIRD_GEAR)
.asObservable()
.subscribe(new Consumer<File>()
{
#Override
public void accept(File file) throws Exception
{
newfile = file;
}
}, new Consumer<Throwable>()
{
#Override
public void accept(Throwable throwable) throws Exception
{
throwable.printStackTrace();
Toast.makeText(getActivity(), throwable.getMessage(), Toast.LENGTH_SHORT).show();
}
});
}
else
{
Toast.makeText(getActivity(), "No image selected", Toast.LENGTH_SHORT).show();
}
}
}
You are calling Matisse.from() on the Activity which you are getting from the getActivity() method, tit must be returning you your MainActivity and the onActivityResult will be called for the MainActivity where you are doing nothing and calling super.onActivityResult().
Possible Solutions: .
Shift your onActivityResult code logic from your AddMessageFragment to MainActivity
Change you Matisse call from Matisse.from(getActivity()) to Matisse.from(this), because looking at the source code of Matisse it also supports Fragment context.
Using the second solution you should get your onActivityResult callback in the fragment and you won't need to change/shift any other code logic.
Hope this helps :)
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 MainActivity class:
#Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
Fragment fragment = getSupportFragmentManager().findFragmentById(R.id.layoutContainer);
fragment.onActivityResult(requestCode, resultCode, data);
}
In AddMessageFragment class:
#Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
// In fragment class callback
}
Replace your activity onActivityResult method by below code
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);
}
}
It will call your fragment onActivityResult after this execute.
OnActivityResult() function works on Activity. I suggest you call this function on your activity and implement your logic inside your fragment onResume() function. In order to get data from Activity use global val.

startActivityforResult from adapter

I have an adapter inside a fragment, in this adapter I am running an activityForResult to an activity.
Calling the adapter from the Fragment
mAdapClinicSchedule = new ClinicScheduleAdapter(getContext(),mScheduleList);
mLvClinicsSchedules.setAdapter(mAdapClinicSchedule);
Adapter's constructor:
public ClinicScheduleAdapter(Context context, ArrayList<String> mScheduleList) {
this.context = context;
this.mScheduleList = mScheduleList;
}
The call to the startActivityForResult from the adapter
case R.id.tvDaysClinicSchedule:
Intent intent = new Intent(context, ScheduleDaysActivity.class);
((Activity)context).startActivityForResult(intent, 2);
break;
The setResult from the activity
case R.id.tvSelectDays:
checkDaysSelected();
Intent returnIntent = new Intent();
returnIntent.putExtra("monday", mondaySelected);
returnIntent.putExtra("tuesday", tuesdaySelected);
returnIntent.putExtra("wednesday", wednesdaySelected);
returnIntent.putExtra("thursday", thursdaySelected);
returnIntent.putExtra("friday", fridaySelected);
returnIntent.putExtra("saturday", saturdaySelected);
returnIntent.putExtra("sunday", sundaySelected);
setResult(Activity.RESULT_OK, returnIntent);
finish();
break;
Creating an onActivityResult interface
public interface OnActivityResult {
void onActivityResult(int requestCode, int resultCode, Intent data);
}
That implements the adapter:
public class ClinicScheduleAdapter
extends BaseAdapter implements View.OnClickListener, OnActivityResult { ... }
In the fragment it overrite the onActivityResult
#Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
mAdapClinicSchedule.onActivityResult(requestCode, resultCode, data);
//super.onActivityResult(requestCode, resultCode, data);
}
But in the adapter, it does not show the toast, I do not know what I can be doing wrong
public void onActivityResult (int requestCode, int resultCode, Intent data) {
if (requestCode == 2) {
if (resultCode == Activity.RESULT_OK) {
Toast.makeText(context, "it worked!", Toast.LENGTH_LONG).show();
}
}
}
From the android documentation:
Of course, the activity that responds must be designed to return a result. When it does, it sends the result as another Intent object. Your activity receives it in the onActivityResult() callback.
Although, if I remember correctly, onActivityResult() will get called on whatever started the activity for result. So if you use the activity to start your new intent, then the activity will receive the result call. This means if you want the fragment to handle it, you'll need to call startActivityForResult(...) on the fragment rather than the activity
fragment source

issue in onActivityResult with sony xperia

i start activity for result to open GPS
then recieve in OnACtivityResult .. it is work fine in some mobiles , but with sony not work , i don't know why
i use nested fragment
start activity
Intent callGPSSettingIntent = new Intent(
android.provider.Settings.ACTION_LOCATION_SOURCE_SETTINGS);
startActivityForResult(
callGPSSettingIntent, openGPSRequest);
then receive in fragment
#Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if (requestCode == openGPSRequest) {
try {
activity.hideProgress();
} catch (Exception e) {
}
activity.replaceCurrentFragment(
FramentNavigationMapInside.getInstance(branche), true, true);
}
}
in main activity
#Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
}
and in every fragment override onActivityResult
and i test it in lenove and samsung and work fine ,, but with sony xperia not work, only onActivityResult which in main activity call
solve my issue by
One of the common problem we always meet in the world of Fragment is: although we could call startActivityForResult directly from Nested Fragment but it appears that onActivityResult would never been called which brought a lot of trouble to handle Activity Result from Nested Fragment.
the solution
So we will call getActivity().startActivityForResult(...) from Fragment instead of just startActivityResult(...) from now on. Like this:
// In Fragment
Intent intent = new Intent(getActivity(), SecondActivity.class);
getActivity().startActivityForResult(intent, 12345);
As a result, all of the result received will be handled at the single place: onActivityResult of the Activity that Fragment is placed on.
Question is how to send the Activity Result to Fragment?
Due to the fact that we couldn't directly communicate with all of the nested fragment in the normal way, or at least in the easy way. And another fact is, every Fragment knows that which requestCode it has to handled since it is also the one that call startActivityForResult. So we choose the way to "broadcast to every single Fragment that is active at time. And let those Fragments check requestCode and do what they want."
Talk about broadcasting, LocalBroadcastManager could do the job but the mechanic is the way too old. I choose another alternative, an EventBus, which has a lot of choices out there. The one that I chose was Otto from square. It is really good at performance and robustness.
dependencies {
compile 'com.squareup:otto:1.3.6'
}
In the Otto way, let's create a Bus Event as a package carry those Activity Result values.
import android.content.Intent;
/**
* Created by nuuneoi on 3/12/2015.
*/
public class ActivityResultEvent {
private int requestCode;
private int resultCode;
private Intent data;
public ActivityResultEvent(int requestCode, int resultCode, Intent data) {
this.requestCode = requestCode;
this.resultCode = resultCode;
this.data = data;
}
public int getRequestCode() {
return requestCode;
}
public void setRequestCode(int requestCode) {
this.requestCode = requestCode;
}
public int getResultCode() {
return resultCode;
}
public void setResultCode(int resultCode) {
this.resultCode = resultCode;
}
public Intent getData() {
return data;
}
public void setData(Intent data) {
this.data = data;
}
}
import android.os.Handler;
import android.os.Looper;
import com.squareup.otto.Bus;
/**
* Created by nuuneoi on 3/12/2015.
*/
public class ActivityResultBus extends Bus {
private static ActivityResultBus instance;
public static ActivityResultBus getInstance() {
if (instance == null)
instance = new ActivityResultBus();
return instance;
}
private Handler mHandler = new Handler(Looper.getMainLooper());
public void postQueue(final Object obj) {
mHandler.post(new Runnable() {
#Override
public void run() {
ActivityResultBus.getInstance().post(obj);
}
});
}
}
And in activity
public class MainActivity extends ActionBarActivity {
...
#Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
ActivityResultBus.getInstance().postQueue(
new ActivityResultEvent(requestCode, resultCode, data));
}
...
}
and in the end handle back data onActivityResult in fragment
public class BodyFragment extends Fragment {
...
#Override
public void onStart() {
super.onStart();
ActivityResultBus.getInstance().register(mActivityResultSubscriber);
}
#Override
public void onStop() {
super.onStop();
ActivityResultBus.getInstance().unregister(mActivityResultSubscriber);
}
private Object mActivityResultSubscriber = new Object() {
#Subscribe
public void onActivityResultReceived(ActivityResultEvent event) {
int requestCode = event.getRequestCode();
int resultCode = event.getResultCode();
Intent data = event.getData();
onActivityResult(requestCode, resultCode, data);
}
};
#Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
// Don't forget to check requestCode before continuing your job
if (requestCode == 12345) {
// Do your job
tvResult.setText("Result Code = " + resultCode);
}
}
...
}
hope this code help any one face this problem

onActivityResult not call in the Fragment

The structure of the app is like this:
tabHost (in Activity) -> contains -> TabFragment(extend base container fragment)
1. The code in Activity:
tabHost.addTab(
tabHost.newTabSpec("home").setIndicator("",
getResources().getDrawable(R.drawable.btn_home)),
HomeFragment.class, null);
2. The code in HomeFragment
(Notice that HomeFragment is not the actual function but a container like this, and it extend BaseContainerFragment):
public class HomeFragment extends BaseContainerFragment {
public Home homeFrag;
private boolean mIsViewInited;
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
return inflater.inflate(R.layout.container_fragment, null);
}
#Override
public void onActivityCreated(Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
if (!mIsViewInited) {
mIsViewInited = true;
initView();
}
}
private void initView() {
homeFrag = new Home();
replaceFragment(homeFrag, false);
}
}
3. BaseContainerFragment
public class BaseContainerFragment extends Fragment {
public void replaceFragment(Fragment fragment, boolean addToBackStack) {
FragmentTransaction transaction = getChildFragmentManager().beginTransaction();
if (addToBackStack) {
transaction.addToBackStack(null);
}
transaction.replace(R.id.container_framelayout, fragment);
transaction.commit();
}
public boolean popFragment() {
boolean isPop = false;
if (getChildFragmentManager().getBackStackEntryCount() > 0) {
isPop = true;
getChildFragmentManager().popBackStack();
}
return isPop;
}
}
4. In the Home (The actual content of the fragment)
UploadType fragment = new UploadType();
Bundle bundle = new Bundle();
bundle.putString("form_type", "request");
fragment.setArguments(bundle);
((BaseContainerFragment)getParentFragment()).replaceFragment(fragment, true);
5. And in the UploadType , I call the camera activity but onActivityResult is only return in the main activity.
startActivityForResult(intent, REQUEST_CAMERA);
public void onActivityResult(int requestCode, int resultCode, Intent data) {
Log.d("test1", "result2");
super.onActivityResult(requestCode, resultCode, data);
}
How can I trigger the onActivityResult at UploadType? Thanks for help.
The reason why this doesn't work is because you are calling startActivityForResult() from within a nested fragment. Android is smart enough to route the result back to an Activity and even a Fragment, but not to a nested Fragment hence why you don't get the callback.
(more information to why that doesn't work here or on stackoverflow)
Now in order to make it work I suggest you manually route the callback to the ChildFragment (=UploadType) in the ParentFragment (=BaseContainerFragment):
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
Fragment uploadType = getChildFragmentManager().findFragmentById(R.id.container_framelayout);
if (uploadType != null) {
uploadType.onActivityResult(requestCode, resultCode, data);
}
super.onActivityResult(requestCode, resultCode, data);
}
In my case, I've done by adding following code in my MainActivity.java
#Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
for (Fragment fragment : getSupportFragmentManager().getFragments()) {
fragment.onActivityResult(requestCode, resultCode, data);
}
}
In your Activity Override onActivityForResult() like this
#Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
}
Now in your fragment u can get the activity result inside this
#Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
Log.d("test1", "result2");
}
Make sure when your are calling start ActivityForResult in your frragment it should be like this
startActivityForResult(intent, REQUEST_CAMERA);
For NavHostFragment of Navigation Architecture Component
If you are using single activity and have fragments inside the NavHostFragment, there is an issue of onActivityResult() of the child fragment of NavHostFragment not getting called.
To fix this issue, you need to call the onActivityResult() of the child fragments manually from inside the onActivityResult() of the host activity. The host activity is the activity that hosts your NavHostFragment.
Here's the Kotlin code for onActivityResult() of your host activity:
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
super.onActivityResult(requestCode, resultCode, data)
val navHostFragment = supportFragmentManager.findFragmentById(R.id.your_nav_host_fragment)
val childFragments = navHostFragment?.childFragmentManager?.fragments
childFragments?.forEach { it.onActivityResult(requestCode, resultCode, data) }
}
TabActivity->ActivityA->FragmentB, it's not work.
use a bad bad bad way:
ActivityA.java
public void onSelectSomething(){
...
startActivityForResult(intent, 22222);
}
#Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
if (mFragment != null) {
mFragment.onActivityResult(requestCode, resultCode, data);
}
}
FragmentB.java
if(getActivity() instanceof ActivityA) {
((RepairerListActivity)getActivity()).onSelectSomething();
}
#Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if (requestCode == 22222) {
// do things
}
}
#Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
// Loop through all child fragments of the activity
for (Fragment fragment : getSupportFragmentManager().getFragments()) {
// check if the current fragment is YourFragment
if (fragment instanceof YourFragment ) {
fragment.onActivityResult(requestCode, resultCode, data);
}
}
}

onActivityResult not being called in custom Fragment or anywhere else attempted

There have been many successful answers to this question, but there's still something I'm not understanding or that I'm doing incorrectly. One answer is implementing onActivityResult in the host Activity, but I guess I don't know which one that is or I'm following it wrong.
And no, I'm not calling getActivity.startActivityForResult(), just startActivityForResult().
Depending on a selection made in FirstActivity, one or more other selections are possible, created using Fragments. One Fragment is ButtonFragment, which when selected, starts OptionsActivity, like so:
public class ButtonFragment extends Fragment
{
.....
#Override
public void onActivityResult(int requestCode, int resultCode, Intent data)
{
super.onActivityResult(requestCode, resultCode, data);
if(resultCode != Activity.RESULT_CANCELED)
{
if(requestCode == OPTIONS_REQUEST_CODE)
{
Bundle extras = data.getExtras();
if (extras != null) {
String selection = (String) extras.get("optionsSelection");
data.setText(selection);
}
}
}
}
private void openOptionsActivity()
{
Intent intent = new Intent(getActivity(), OptionsActivity.class);
intent.putExtra("optionsArray", options);
startActivityForResult(intent, OPTIONS_REQUEST_CODE);
}
}
This fragment is being added in BaseActivity:
public class BaseActivity extends FragmentActivity
{
.....
fm.beginTransaction().add(
R.id.FragmentContainer, frag).commitAllowingStateLoss();
fm.executePendingTransactions();
#Override
public void onActivityResult(int requestCode, int resultCode, Intent data)
{
super.onActivityResult(requestCode, resultCode, data);
finish();
}
}
Inside OptionsActivity:
public class OptionsActivity extends BaseSpinnerActivity
{
.....
private class OptionsAdapter extends BaseSpinnerAdapter
{
public OptionsAdapter(Context context, Object[] values)
{
super(context, values);
}
protected void fillRow(ViewHolder holder, int position)
{
String option = options[position];
if(option != null) {
holder.text.setText(option);
}
}
protected void onRowSelect(View v)
{
Intent returnIntent = new Intent();
String optionSelection = (String)v.getTag();
returnIntent.putExtra("optionSelected", optionSelection);
setResult(RESULT_OK, returnIntent);
finish();
}
}
#Override
public void onActivityResult(int requestCode, int resultCode, Intent data)
{
super.onActivityResult(requestCode, resultCode, data);
finish();
}
}
The same thing is done inside BaseSpinnerActivity, which extends from ListActivity. (I know, should use FragmentActivity, but I haven't had a chance to convert it yet.)
None of these onActivityResult()'s are being called.
What am I missing or doing wrong? Any help is appreciated!

Categories

Resources