Challenge 2 problem to return data to activity

Hi
I’ve trying to figure out what is my error but I couldn’t find it.
I have created an additional Dialog to let the user chose whether to change date or time.
But when I try to change the Date I can’t send the result back.
In order to call the Activity which will host the DateDialog I use startActivityForResult from the aditional dialog and I set the result by using getActivity().setResult(resultCode, intent); followed by getActivity().finish(); in order to finish the activity.

The dateDialog is displayed properly, I show all the code involved:

Crime Fragment(Here I only modified how I call the OptionFragment which let me chose what to change : date/time)

        public class CrimeFragment extends Fragment {
            private static final String ARG_CRIME_ID = "crime_id";
            private static final String DIALOG_DATE = "DiaglogDate";

            private static final int REQUEST_DATE = 0;

            private Crime mCrime;
            private EditText mTitleField;
            private Button mDateButton;
            private CheckBox mSolvedCheckBox;

            public static CrimeFragment newInstance(UUID crimeId) {
                Bundle args = new Bundle();
                args.putSerializable(ARG_CRIME_ID, crimeId);
                CrimeFragment fragment = new CrimeFragment();
                fragment.setArguments(args);
                return fragment;
            }


            @Override
            public void onCreate(Bundle savedInstanceState) {
                super.onCreate(savedInstanceState);
                UUID uuidCorrectWay = (UUID) getArguments().getSerializable(ARG_CRIME_ID);         
                mCrime = CrimeLab.get(getActivity())
                        .getCrime(uuidCorrectWay);
            }

            @Override
            public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
                View v = inflater.inflate(R.layout.fragment_crime, container, false);
                mTitleField = (EditText) v.findViewById(R.id.crime_title);
                mTitleField.setText(mCrime.getTitle());
                mTitleField.addTextChangedListener(new TextWatcher() {
                    @Override
                    public void beforeTextChanged(CharSequence charSequence, int i, int i1, int i2) {
                    }

                    @Override
                    public void onTextChanged(CharSequence charSequence, int i, int i1, int i2) {
                        mCrime.setTitle(charSequence.toString());
                    }

                    @Override
                    public void afterTextChanged(Editable editable) {
                        // This one too is left blank.
                    }
                });
                
mDateButton = (Button) v.findViewById(R.id.crime_date);
                updateDate();



                mDateButton.setOnClickListener(new View.OnClickListener() {
                    @Override
                    public void onClick(View view) {
                        FragmentManager fragmentManager = getFragmentManager();
                        // OptionDialog
                        OptionDialogFragment optionDialogFragment = OptionDialogFragment.newInstance(mCrime.getDate());
                        optionDialogFragment.setTargetFragment(CrimeFragment.this,REQUEST_OPTION);
                        optionDialogFragment.show(fragmentManager,TAG_OPTION);

                    }
                });
                mSolvedCheckBox = (CheckBox) v.findViewById(R.id.crime_solved);
                mSolvedCheckBox.setChecked(mCrime.isSolved());
                mSolvedCheckBox.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
                    @Override
                    public void onCheckedChanged(CompoundButton compoundButton, boolean b) {
                        mCrime.setSolved(b);
                    }
                });


                return v;
            }

            @Override
            public void onActivityResult(int requestCode, int resultCode, Intent data) {
                if (resultCode != Activity.RESULT_OK) {
                    return;
                }
                Date date;
                switch (requestCode){
                    case REQUEST_DATE:
                        date = DatePickerFragment.getDate(data);
                        mCrime.setDate(date);
                        updateDate();
                        break;
                    case REQUEST_OPTION:
                        date = OptionDialogFragment.getDate(data);
                        mCrime.setDate(date);
                        updateDate();
                        break;
                }
            }
    private void updateDate() {
            mDateButton.setText(mCrime.getDate().toString());
        }

        private static final String TAG_OPTION = "com.bignerdranch.criminalintent.crimefragment.option";
        private final int REQUEST_OPTION = 1;

OptionDialog Is the custom dialog used to choose to change Time or Date

public class OptionDialogFragment extends DialogFragment {


    private static final String ARG_DATE = "date";

    public static OptionDialogFragment newInstance(Date date) {
        Bundle bundle = new Bundle();
        bundle.putSerializable(ARG_DATE, date);
        OptionDialogFragment optionDialogFragment = new OptionDialogFragment();
        optionDialogFragment.setArguments(bundle);
        return optionDialogFragment;
    }

    private static final int REQUEST_TIME = 0;
    private static final int REQUEST_DATE = 1;
    private static final String TAG_DIALOG_TIME = "com.bignerdranch.criminalintent.optiondialog.time";
    private static final String TAG_DIALOG_DATE = "com.bignerdranch.criminalintent.optiondialog.date";

    private Date mDate;

    @NonNull
    @Override
    public Dialog onCreateDialog(@Nullable Bundle savedInstanceState) {
        mDate = (Date) getArguments().getSerializable(ARG_DATE);
        AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
        builder.setMessage("What do you want to Edit?")
                .setPositiveButton("Time", new DialogInterface.OnClickListener() {
                    @Override
                    public void onClick(DialogInterface dialogInterface, int i) {
                        TimePickerFragment timePickerFragment = TimePickerFragment.newInstance(mDate);
                        timePickerFragment.setTargetFragment(OptionDialogFragment.this, REQUEST_TIME);
                        FragmentManager fragmentManager = getFragmentManager();
                        timePickerFragment.show(fragmentManager, TAG_DIALOG_TIME);
                    }
                })
                .setNeutralButton("Date", new DialogInterface.OnClickListener() {
                    @Override
                    public void onClick(DialogInterface dialogInterface, int i) {
                        // Challenge 2 Call DatePickerActivity
                        Intent intent = DatePickerActivity.newIntent(getContext(),mDate);
                        startActivityForResult(intent,REQUEST_DATE_ACTIVITY);
                    }
                });
        return builder.create();
    }


    @Override
    public void onActivityResult(int requestCode, int resultCode, Intent data) {
        if (resultCode != Activity.RESULT_OK) {
            return;
        }
        if (data == null) {
            return;
        }
        switch (requestCode) {
            case REQUEST_TIME:
                mDate = TimePickerFragment.getDate(data);
                break;
            case REQUEST_DATE:
                mDate = DatePickerFragment.getDate(data);
                break;
            case REQUEST_DATE_ACTIVITY:
                mDate = DatePickerFragment.getDate(data);
                break;
            default:
                Log.d(TAG, "No idea which activity called");
        }

        sendResult(mDate);

    }

    private void sendResult(Date date) {
        Intent data = new Intent();
        data.putExtra(EXTRA_RETURN_DATE, date);
        getTargetFragment()
                .onActivityResult(getTargetRequestCode(), Activity.RESULT_OK, data);
    }

    private static final String TAG = OptionDialogFragment.class.getName();
    private static final String EXTRA_RETURN_DATE = "com.bignerdranch.criminalintent.finaldate";
    private static final int REQUEST_DATE_ACTIVITY = 2;

    public static Date getDate(Intent data){
        return (Date) data.getSerializableExtra(EXTRA_RETURN_DATE);
    }
}

DatePickerActivity which host the date fragment show below

public class DatePickerActivity extends SingleFragmentActivity {
    private static final String EXTRA_DATE = "com.bignerdranch.criminalintent.extra.date.activity";

    public static Intent newIntent(Context context, Date date) {
        Intent intent = new Intent(context, DatePickerActivity.class);
        intent.putExtra(EXTRA_DATE, date);
        return intent;
    }

    @Override
    protected Fragment createFragment() {
        Date date = (Date) getIntent().getSerializableExtra(EXTRA_DATE);
        return DatePickerFragment.newInstance(date);
    }
}

And finally the DatePickerFragment used to modify the date.

public class DatePickerFragment extends DialogFragment {

    private static final String ARG_DATE = "date";
    public static final String EXTRA_DATE = "com.bignerdranch.criminalintent.date";
    private DatePicker mDatePicker;
    private Button mOkButton;

    private Date mDate;

    
    public static DatePickerFragment newInstance(Date date) {
        Bundle args = new Bundle();
        args.putSerializable(ARG_DATE, date);

        DatePickerFragment datePickerFragment = new DatePickerFragment();
        datePickerFragment.setArguments(args);
        return datePickerFragment;
    }


    @Nullable
    @Override
    public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {

        Log.d(TAG, "onCreateView");

        mDate = (Date) getArguments().getSerializable(ARG_DATE);
        View view = inflater.inflate(R.layout.dialog_date, container, false);
        final Calendar calendar = Calendar.getInstance();
        calendar.setTime(mDate);
        int year = calendar.get(Calendar.YEAR);
        int month = calendar.get(Calendar.MONTH);
        int day = calendar.get(Calendar.DAY_OF_MONTH);

        mDatePicker = (DatePicker) view.findViewById(R.id.dialog_date_picker);
        mDatePicker.init(year, month, day, null);
        mOkButton = (Button) view.findViewById(R.id.ok_date_button);
        mOkButton.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                int year = mDatePicker.getYear();
                int month = mDatePicker.getMonth();
                int day = mDatePicker.getDayOfMonth();
                int hour = calendar.get(Calendar.HOUR);
                int minute = calendar.get(Calendar.MINUTE);
                calendar.set(year, month, day, hour, minute);
                sendResult(Activity.RESULT_OK, calendar.getTime());
            }
        });

        return view;
    }
    private void sendResult(int resultCode, Date date) {
        Intent intent = new Intent();
        intent.putExtra(EXTRA_DATE, date);

        if (getTargetFragment() == null) {
            // Created from Activity
            getActivity()
                    .setResult(
                            resultCode
                            , intent);
            getActivity().finish();
        } else {
            // Created as Fragment not from Activity
            Log.d(TAG,"TargetFragment =" + getTargetFragment().toString());
            getTargetFragment() // Here we Obtain the Fragment who invoked this one
                    .onActivityResult // Here we call the method onActivityResult of the fragment
                    (getTargetRequestCode() // Obtain the TargetRequestCode
                            , resultCode // ResultCode
                            , intent); // intent
        }
    }

    private static final String TAG = DatePickerFragment.class.toString();
    private static final String DIALOG_TIME = "dialog_time";
    private static final int REQUEST_TIME = 1;


    @Override
    public void onActivityResult(int requestCode, int resultCode, Intent data) {
        if (resultCode != Activity.RESULT_OK) {
            Log.d(TAG, "Result != ok");
            return;
        }
        if (requestCode == REQUEST_TIME) {
            // EXTRACT USEFUL DATA FROM INTENT
            mDate = TimePickerFragment.getDate(data);
            sendResult(Activity.RESULT_OK, mDate);
        }
    }



    public static Date getDate(Intent data) {
        return (Date) data.getSerializableExtra(EXTRA_DATE);
    }
}

I have tried using several break points in different parts of the program but after DatePickerFragment uses setResult and finishing the host activity neither onActivityResult from OptionDialogFragment nor CrimeFragment is called even though I try implementing calling super.onActivityResult, I haven’t include it because I tested after.
With the code shown I can set up a different time.
I believe the problem is in how I call DatePickerActivity from OptionDialog or how I setResult but unfortunately I can’t find the issue.

I solved :slight_smile: But I don’t really understand it.
Hope you can help me.

After having a good rest, and reading again some solutions already posted here, I realized that the biggest difference was that solutions call From CrimeActivity to CrimeFragment after that to DatePickerActivity and finally to DatePickerFragment .

What I was doing was calling From CrimeActivityto CrimeFragment after that to OptionDialogFragment and then DatePickerActivity and finally to DatePickerFragment.

The problem was that I couln’t receive result in onActivityResult of OptionDialogFragment my guess it is because is a Fragment created from another Fragment instead of an Activity, Is that true? Can You received result in a Child Fragment when another fragment have created it, and It call an Activity?

So How did I solved?
I used in OptionDialogFragment

getTargetFragment.startActivityForResult

Doing this I get the target Fragment, which is CrimeFragment, and It is hosted by an Activity,CrimeActivity , and I can return Result with setResult .

I would like to know if there is a better way to obtain a result in a child fragment that was created by another fragment and call an activity.