onActivityResult Receiving Null Date


#1

Hi, i am trying to complete the hard challenge and it is going ok, my app shows a dialog that gives the user an option to change date and time, i have only been concentrating on the date section at the moment, but am having trouble with the onActivityResult, for some reason if the user selects the date button it gives an error

apparently before the dialog for the datePicker has even opened it is running the code in the onActivityResult

[code]if(requestCode == REQUEST_DATE){

		Date date = (Date)data.getSerializableExtra(DatePickerFragment.EXTRA_DATE);
		Log.d("date is" + date, TAG, null);
		mCrime.setDate(date);
		updateDate();
	}[/code]

The log above is displaying the date as null, which when trying to update is causing the error, but i am not sure why it is running this code before the user has even changed the date.

Here is the rest of the code

DatePickerFragment.java

[code]package com.shoutr.criminalintent;

import java.util.Calendar;
import java.util.Date;
import java.util.GregorianCalendar;

import android.app.Activity;
import android.app.AlertDialog;
import android.app.Dialog;
import android.content.DialogInterface;
import android.content.Intent;
import android.os.Bundle;
import android.support.v4.app.DialogFragment;
import android.view.View;
import android.widget.DatePicker;
import android.widget.DatePicker.OnDateChangedListener;

//Instances of DialogFragments are managed by the FragmentManager of the hosting activity
public class DatePickerFragment extends DialogFragment {

public static final String EXTRA_DATE = "com.shoutr.android.criminalintent.date";
private Date mDate;

//to get the date in the DatePickerFragment is to stash them in the arguments bundle
public static DatePickerFragment newInstance(Date date){
	
	Bundle args = new Bundle();
	args.putSerializable(EXTRA_DATE, date);
	
	DatePickerFragment fragment = new DatePickerFragment();
	fragment.setArguments(args);
	
	return fragment;
}

// this method gets the new date and inputs it into the intent with the key of EXTRA_DATE
private void sendResult(int resultCode){
	
	if(getTargetFragment() == null)
		return;
	
	Intent i = new Intent();
	i.putExtra(EXTRA_DATE, mDate);
	
	getTargetFragment().onActivityResult(getTargetRequestCode(), resultCode, i);
}

//this is the createdialog, it sets the dialog up, it first
@Override
public Dialog onCreateDialog(Bundle savedInstanceState){
	//Date Extraction
	mDate = (Date)getArguments().getSerializable(EXTRA_DATE);
	
	//Create a calendar to get the year, month, day
	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);
	
	//inflate the view and set it on the dialog
	View v = getActivity().getLayoutInflater().inflate(R.layout.dialog_date, null);
	
	//DATEPICKER INITIALISATION
	DatePicker datePicker = (DatePicker)v.findViewById(R.id.dialog_date_datePicker);
	datePicker.init(year, month, day, new OnDateChangedListener(){
		public void onDateChanged(DatePicker view, int year, int month, int day){
			
			//Translate year, month, day into a Date object using a calendar
			mDate = new GregorianCalendar(year, month, day).getTime();
			
			//Update argument to preserve selected value on rotation
			getArguments().putSerializable(EXTRA_DATE, mDate);
		}
		
	});
	//Create a fluent interface for creating the AlertDialog instance
	return new AlertDialog.Builder(getActivity())
			.setView(v)
			.setTitle(R.string.date_picker_title)
			.setPositiveButton(
					android.R.string.ok,
					new DialogInterface.OnClickListener(){
						
						public void onClick(DialogInterface dialog, int which){
							
							sendResult(Activity.RESULT_OK);
						}
					})
			.create();
}

}[/code]

CrimeFragment.java

[code]package com.shoutr.criminalintent;

import java.util.Calendar;
import java.util.Date;
import java.util.GregorianCalendar;
import java.util.UUID;

import android.app.Activity;
import android.content.Intent;
import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentManager;
import android.text.Editable;
import android.text.TextWatcher;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Button;
import android.widget.CheckBox;
import android.widget.CompoundButton;
import android.widget.CompoundButton.OnCheckedChangeListener;
import android.widget.EditText;

public class CrimeFragment extends Fragment {

public static final String EXTRA_CRIME_ID = "com.shoutr.android.criminalintent.crime_id";

//create the tag for the alert dialog
public static final String DIALOG_DATE = "date";

//create the tag for the choice for dialog
public static final int DIALOG_CHOICE = 0;

//initialise the request code for the date dialog
private static final int REQUEST_DATE = 0;
//initialise the request code for the choice dialog
private static final int REQUEST_CHOICE = 0;


private static final String TAG = null;


//Declare the crime instance
private Crime mCrime;
//declare the text field	
private EditText mTitleField;
//Declare the date Button
private Button mDateButton;

//declare the checkbox
private CheckBox mSolvedCheckBox;



//onCreate method
@Override
public void onCreate(Bundle savedInstanceState){
	//retrieve the previous state
	super.onCreate(savedInstanceState);
	
	//SHORTCUT WAY
	//get the uuid out of the called intent see getIntent in the context of the activity getActivity
	//UUID crimeId = (UUID)getActivity().getIntent().getSerializableExtra(EXTRA_CRIME_ID);
	//SHORTCUT WAY
	
	//getting crime id from the arguments bundle
	UUID crimeId = (UUID)getArguments().getSerializable(EXTRA_CRIME_ID);
	
	//fetch the crime from the crimeLab
	mCrime = CrimeLab.get(getActivity()).getCrime(crimeId);
	
}

//update the date
private void updateDate(){
	
	mDateButton.setText(mCrime.getDate().toString());
	
}


@Override
public View onCreateView(LayoutInflater inflater, ViewGroup parent, Bundle savedInstanceState){
	//inflate the view 
	View v = inflater.inflate(R.layout.fragment_crime,  parent, false);
	//call the text field for crime title
	mTitleField = (EditText)v.findViewById(R.id.crime_title);
	
	//update view object for title
	mTitleField.setText(mCrime.getTitle());
	//add text listener to it
	mTitleField.addTextChangedListener(new TextWatcher(){

		@Override
		public void afterTextChanged(Editable c) {
			// TODO Auto-generated method stub
			
		}

		@Override
		public void beforeTextChanged(CharSequence c, int start,
				int count, int after) {
			// TODO Auto-generated method stub
			
		}
		@Override
		public void onTextChanged(CharSequence c, int start, int before, int count) {
			//set the contents of the text box to the crime title
			mCrime.setTitle(c.toString());
			
		}

	});
	//initialise the button for the date
	mDateButton = (Button)v.findViewById(R.id.crime_date);
	//set the button text to the crime date
	
	//make sure of no user interaction
	//mDateButton.setEnabled(false);
	mDateButton.setOnClickListener(new View.OnClickListener() {
		//show the datepickerfragment when the button is pressed
		@Override
		public void onClick(View v) {		
			//open the choiceDialog fragment
			FragmentManager fm = getActivity().getSupportFragmentManager();
	        DialogChoiceFragment dialogFragment = new DialogChoiceFragment();
	        dialogFragment.setTargetFragment(CrimeFragment.this, REQUEST_CHOICE);
	        dialogFragment.show(fm, null);
		}
	});
	
	
	updateDate();
	//initialise the checkbox for solved
	mSolvedCheckBox = (CheckBox)v.findViewById(R.id.crime_solved);
	//update the solved status for the crime
	mSolvedCheckBox.setChecked(mCrime.isSolved());
	//create the on change listener for the checkbox
	mSolvedCheckBox.setOnCheckedChangeListener(new OnCheckedChangeListener(){

		@Override
		public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
			// TODO Auto-generated method stub
			
			//set the new solved status
			mCrime.setSolved(isChecked);
		}	
	});
	return v;
}


//Attaching arguments to fragment = more flexibility / crimeActivity will call CrimeFragment.newInstance when it needs to create a crimeFragment
public static CrimeFragment newInstance(UUID crimeId){
	
	Bundle args = new Bundle();
	args.putSerializable(EXTRA_CRIME_ID, crimeId);
	
	CrimeFragment fragment = new CrimeFragment();
	fragment.setArguments(args);
	
	return fragment;
}


//Respond to the date dialog
@Override
public void onActivityResult(int requestCode, int resultCode, Intent data){
	
	if(resultCode != Activity.RESULT_OK) return;
	if(requestCode == REQUEST_DATE){
		
		Date date = (Date)data.getSerializableExtra(DatePickerFragment.EXTRA_DATE);
		Log.d("date is" + date, TAG, null);
		mCrime.setDate(date);
		updateDate();
	}
	
	if(requestCode == REQUEST_CHOICE){
		int choice = data.getIntExtra(DialogChoiceFragment.EXTRA_CHOICE, 0);
		//Log.d("choice dialog", "choice as 2");
		if(choice == 1){
			//openTimeFragment();
			
		}else if(choice == 2){
			Log.d("choice dialog", "choice as 2");
			openDateFragment();
		}
	}

}

public void openDateFragment(){
	FragmentManager fm = getActivity().getSupportFragmentManager();
	//Dont do the below call the newInstance instead
	//DatePickerFragment dialog = new DatePickerFragment();
	DatePickerFragment dialog = DatePickerFragment.newInstance(mCrime.getDate());
	//set the target fragment
	dialog.setTargetFragment(CrimeFragment.this, REQUEST_DATE);
	dialog.show(fm,  DIALOG_DATE);
	
}

}
[/code]

DialogChoiceFragment

[code]package com.shoutr.criminalintent;

import java.util.Date;

import android.app.Activity;
import android.app.AlertDialog;
import android.app.Dialog;
import android.content.DialogInterface;
import android.content.Intent;
import android.os.Bundle;
import android.support.v4.app.DialogFragment;
import android.view.View;

public class DialogChoiceFragment extends DialogFragment {

public static final String EXTRA_CHOICE = "com.shoutr.android.criminalintent.choice";
private Date mDate;

private int mChoice = 0;
public static final int TIME_CHOICE = 1;
private static final int DATE_CHOICE = 2;

@Override
public Dialog onCreateDialog(Bundle savedInstanceState){
			
	//inflate the view and set it on the dialog
	View v = getActivity().getLayoutInflater().inflate(R.layout.dialog_date_choice, null);
	
	
	//Create a fluent interface for creating the AlertDialog instance
	return new AlertDialog.Builder(getActivity())
			.setView(v)
			.setTitle(R.string.dialog_choice_title)
			.setPositiveButton(
					R.string.dialog_time_choice,
					new DialogInterface.OnClickListener(){
						
						public void onClick(DialogInterface dialog, int which){
							mChoice = TIME_CHOICE;
							sendResult(Activity.RESULT_OK);
						}
					})
			.setNegativeButton(
					R.string.dialog_date_choice,
					new DialogInterface.OnClickListener() {
						
						@Override
						public void onClick(DialogInterface dialog, int which) {
							// TODO Auto-generated method stub
							mChoice = DATE_CHOICE;
							sendResult(Activity.RESULT_OK);
							
						}
					})
			
			.create();
}

private void sendResult(int resultCode){
	
	if(getTargetFragment() == null)
		return;
	
	Intent i = new Intent();
	i.putExtra(EXTRA_CHOICE, mChoice);
	
	getTargetFragment().onActivityResult(getTargetRequestCode(), resultCode, i);
}

}

[/code]

Thanks for any and all help


#2

This code Log.d("date is" + date, TAG, null);
should be Log.d(TAG, "date is" + date.toString());