1

I searched and found nothing to explain why null is the result of Intent, such as:

How to get Date extra from an intent?

Android: Passing Date in putExra

It appears that Intent does not pass anything in my code as my code results in a NullPointerException (I am working through "Android Programming" by Big Nerd Ranch):

First, I declare and define the key EXTRA_DATE and create the Intent in CrimeFragment's code (NOTE: this is the TAG used in the LogCat output shown below the code), in the else statement:

      public static final String EXTRA_DATE = "date";
      private static Date date = null;
      ...

        if (small screen) {
             //small screen code
        } else {
            Log.d(TAG, "Large screen: activity");
            date = mCrime.getDate();
            Log.d(TAG, "date is " + date);
            Intent intent = new Intent(getContext(), DatePickerActivity.class);
            intent.putExtra(EXTRA_DATE, date);
            startActivityForResult(intent, REQUEST_DATE);
        }

As can be seen in the LogCat output for this code section (below), the 'date' variable has a value at this point, just before sending it out with Intant:

CrimeFragment: Large screen: activity
CrimeFragment: date is Mon Oct 16 18:19:24 CDT 2017

startActivityForResult then launches DatePickerActivity, and enters createFragment (Android Studio suggested that I add the import, which I did):

import static com.bignerdranch.android.criminalintent.DatePickerFragment.EXTRA_DATE;

public class DatePickerActivity extends SingleFragmentActivity {
    private final String TAG = "DatePickerActivity";
    private static final int REQUEST_DATE = 0;

@Override
protected Fragment createFragment() {
    Log.d(TAG, "Entered createFragment");
    Date date = (Date) getIntent().getSerializableExtra(EXTRA_DATE);
    Log.d(TAG,"date = " + date);
    return DatePickerFragment.newInstance(date);
}

As noted in the import statement, DatePickerFragment is referenced in the import statement:

              public static DatePickerFragment newInstance(Date date){
                    Log.d(TAG, "Entered newInstance");
                    Log.d(TAG, "Date is " + date);
                    Bundle args = new Bundle();
                    args.putSerializable(EXTRA_DATE, date);
                    DatePickerFragment fragment = new DatePickerFragment();
                    fragment.setArguments(args);
                   return fragment;
               }

SingleFragmentActivity is extended:

        public abstract class SingleFragmentActivity extends AppCompatActivity {
            protected abstract Fragment createFragment();
            private static final String TAG= "SingleFragmentActivity";

            @Override
            protected void onCreate(Bundle savedInstanceState) {
                super.onCreate(savedInstanceState);
                Log.d(TAG, "Entered onCreate");
                setContentView(R.layout.activity_fragment);

                FragmentManager fm = getSupportFragmentManager();
                 //fragment_container is the top level FrameLayout in activity_fragment
                Fragment fragment = fm.findFragmentById(R.id.fragment_container);

                if (fragment == null){
                    fragment = createFragment();
                    fm.beginTransaction().add(R.id.fragment_container, fragment).commit();
                }
            }
        }

But the Intent fails immediately as shown by the LogCat line in which 'date = null':

CrimeFragment: Entered onPause
CrimeFragment: Entered onPause
SingleFragmentActivity: Entered onCreate
DatePickerActivity: Entered createFragment
DatePickerActivity: date = null

This null value is now passed to DatePickerFragment:

public class DatePickerFragment extends DialogFragment {
    public static final String EXTRA_DATE = "com.bignerdranch.android.criminalintent.date";
    private static final String ARG_DATE = "Date";
    private static final String TAG = "DatePickerFragment";

    private DatePicker mDatePicker;

public static DatePickerFragment newInstance(Date date){
    Log.d(TAG, "Entered newInstance");
    Log.d(TAG, "Date is " + date);
    Bundle args = new Bundle();
    args.putSerializable(ARG_DATE, date);
    DatePickerFragment fragment = new DatePickerFragment();
    fragment.setArguments(args);
    return fragment;
}

public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container,
                       @Nullable Bundle savedInstanceState){
    Log.d(TAG, "Entered onCreateView");
    Date date = (Date) getArguments().getSerializable(EXTRA_DATE);
    Log.d(TAG, "Date equals: " + date);
    Calendar calendar = Calendar.getInstance();
    calendar.setTime(date);

Until the NullPointerException happens:

java.lang.RuntimeException: Unable to start activity 
ComponentInfo{com.bignerdranch.android.criminalintent/com.bignerdranch. 
android.criminalintent.DatePickerActivity}: java.lang.NullPointerException:
Attempt to invoke virtual method ‘long java.util.Date.getTime()’ on a null 
object reference

As seen above in the LogCat output for DatePickerActivity, the date variable is null and so null is passed from that point on as seen in the following LogCat snippet from the onCreateView code above.

DatePickerFragment: Entered newInstance
DatePickerFragment: Date is null
DatePickerFragment: Entered onCreateView
DatePickerFragment: Date equals: null
AndroidRuntime: Shutting down VM

Through all my reading, including all posts in stackoverflow.com, it seems that this should just work, that Intent should simply pass the Date value from CrimeFragment to DatePickerFragment, but it doesn't as the value of 'Date equals null' shows.

It seems that there's nothing more for me to do, that Intent should just pass 'date', but it doesn't.

Jeff
  • 431
  • 4
  • 16
  • I don't know what 'SingleFragmentActivity' is, but just to confirm, you do not need to call getActivity.getIntent? Also, are you sure that the EXTRA_DATE keys are exactly the same? – AChez9 Oct 17 '17 at 21:03
  • Take a look at the accepted answer to this post: https://stackoverflow.com/questions/6751583/is-there-a-method-that-works-like-start-fragment-for-result – Barns Oct 17 '17 at 22:12
  • ACex9 and Barns52, it must be the EXTRA_DATE key. I really don't understand how it must be referenced in the various files such that the retrieving class knows what it is. I am updating the original post to show how I incorrectly referenced that key so that others can see the problem more clearly and then will update this with the correction to help others. – Jeff Oct 18 '17 at 15:09

2 Answers2

0

Old big nerd ranch man takes me back yep

DatePickerActivity does not know what extra_date is. There is no reference for it in your class, it is not a variable.

usually intent extras go like

intent.putExtra(String key, Object object);

you did intent.putExtra(EXTRA_DATE, date); which is fine but in the retrieving class you need to know what the EXTRA_DATE value is.

sdfbhg
  • 109
  • 5
  • This is probably where my problem lies. What I've read hasn't obviously, at least to me, explained how these tags are to be referenced in the files that they are used in. I am going through my code to update my original post to clarify how I referenced EXTRA_DATE throughout the various files. I will then try to figure out how to properly reference EXTRA_DATE throughout my code and post corrections to help others. – Jeff Oct 18 '17 at 15:05
0

Thanks to sdfbhg, AChez9 and Barns52! You guys nailed it. Because I didn't really understand the key issue I hadn't properly identified the EXTRA_DATE key. So, now being pointed in that direction, I searched with a new focus and found:

naming convention for passing data through extras in android

that pointed to:

https://developer.android.com/training/basics/firstapp/starting-activity.html#StartActivity

in that page's code, there was the answer:

String message = intent.getStringExtra(MainActivity.EXTRA_MESSAGE);

Note that the source file's name is part of the key. So, I changed one line in my code in DatePickerActivity from:

    Date date = (Date) intent.getSerializableExtra(EXTRA_DATE);

To:

    Date date = (Date) intent.getSerializableExtra(CrimeFragment.EXTRA_DATE);

And the NullPointerException is no more because I now reference the source file in the retrieval file. The lesson is to properly reference your keys. Now I know that I didn't know.

One more thing. I experimented and found that adding: import static com.bignerdranch.android.criminalintent.CrimeFragment.EXTRA_DATE; provided the information for Date date = (Date) intent.getSerializableExtra(EXTRA_DATE); to work correctly. So, there are two ways of providing the key reference information to your Intent call.

Jeff
  • 431
  • 4
  • 16