nullPointerException Error when trying to save


#1

I have gotten to code Listing 17.4. Each time I try to save to the JSON file I get a nullPointerException Error. I have tried running CriminalIntent on my emulator and my phone, both result in the same error. I’m stumped, any help is appreciated!

Begin EDIT - After an extensive use of Log statements, here is an updated LogCat. I noticed that my Log statements in Crime.java (public JSONObject) or CriminalIntentJSONSerializer.java never are executed.

New LogCat

03-26 14:00:24.935: I/Crime Lab(2409): Crime.java -- in Crime() 03-26 14:00:24.945: I/Crime Lab(2409): CrimeLab.java -- in CrimeLab get 03-26 14:00:24.945: I/Crime Lab(2409): CrimeLab.java -- in addCrime 03-26 14:00:24.985: I/Crime Lab(2409): CrimeLab.java -- in CrimeLab get 03-26 14:00:24.985: I/Crime Lab(2409): CrimeLab.java -- in ArrayList 03-26 14:00:25.005: I/Crime Lab(2409): CrimeFragment.java -- in onCreate 03-26 14:00:25.005: I/Crime Lab(2409): CrimeLab.java -- in CrimeLab get 03-26 14:00:25.005: I/Crime Lab(2409): CrimeLab.java -- in getCrime UUID 03-26 14:00:25.065: D/dalvikvm(2409): GC_FOR_ALLOC freed 222K, 6% free 4471K/4720K, paused 13ms, total 13ms 03-26 14:00:33.285: I/Crime Lab(2409): CrimeFragment.java -- in onPause 03-26 14:00:33.285: I/Crime Lab(2409): CrimeLab.java -- in CrimeLab get 03-26 14:00:33.285: I/Crime Lab(2409): CrimeLab.java -- in saveCrimes() 03-26 14:00:33.295: E/Crime Lab(2409): Error saving crimes: 03-26 14:00:33.295: E/Crime Lab(2409): java.lang.NullPointerException 03-26 14:00:33.295: E/Crime Lab(2409): at bigdaddycoding.criminalintent.CrimeLab.saveCrimes(CrimeLab.java:60) 03-26 14:00:33.295: E/Crime Lab(2409): at bigdaddycoding.criminalintent.CrimeFragment.onPause(CrimeFragment.java:126) 03-26 14:00:33.295: E/Crime Lab(2409): at android.support.v4.app.Fragment.performPause(Fragment.java:1661) 03-26 14:00:33.295: E/Crime Lab(2409): at android.support.v4.app.FragmentManagerImpl.moveToState(FragmentManager.java:973) 03-26 14:00:33.295: E/Crime Lab(2409): at android.support.v4.app.FragmentManagerImpl.moveToState(FragmentManager.java:1104) 03-26 14:00:33.295: E/Crime Lab(2409): at android.support.v4.app.FragmentManagerImpl.moveToState(FragmentManager.java:1086) 03-26 14:00:33.295: E/Crime Lab(2409): at android.support.v4.app.FragmentManagerImpl.dispatchPause(FragmentManager.java:1898) 03-26 14:00:33.295: E/Crime Lab(2409): at android.support.v4.app.FragmentActivity.onPause(FragmentActivity.java:412) 03-26 14:00:33.295: E/Crime Lab(2409): at android.app.Activity.performPause(Activity.java:5235) 03-26 14:00:33.295: E/Crime Lab(2409): at android.app.Instrumentation.callActivityOnPause(Instrumentation.java:1233) 03-26 14:00:33.295: E/Crime Lab(2409): at android.app.ActivityThread.performPauseActivity(ActivityThread.java:3050) 03-26 14:00:33.295: E/Crime Lab(2409): at android.app.ActivityThread.performPauseActivity(ActivityThread.java:3019) 03-26 14:00:33.295: E/Crime Lab(2409): at android.app.ActivityThread.handlePauseActivity(ActivityThread.java:2997) 03-26 14:00:33.295: E/Crime Lab(2409): at android.app.ActivityThread.access$800(ActivityThread.java:141) 03-26 14:00:33.295: E/Crime Lab(2409): at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1273) 03-26 14:00:33.295: E/Crime Lab(2409): at android.os.Handler.dispatchMessage(Handler.java:99) 03-26 14:00:33.295: E/Crime Lab(2409): at android.os.Looper.loop(Looper.java:137) 03-26 14:00:33.295: E/Crime Lab(2409): at android.app.ActivityThread.main(ActivityThread.java:5103) 03-26 14:00:33.295: E/Crime Lab(2409): at java.lang.reflect.Method.invokeNative(Native Method) 03-26 14:00:33.295: E/Crime Lab(2409): at java.lang.reflect.Method.invoke(Method.java:525) 03-26 14:00:33.295: E/Crime Lab(2409): at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:737) 03-26 14:00:33.295: E/Crime Lab(2409): at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:553) 03-26 14:00:33.295: E/Crime Lab(2409): at dalvik.system.NativeStart.main(Native Method) 03-26 14:00:33.305: I/Crime Lab(2409): CrimeLab.java -- in CrimeLab get 03-26 14:00:33.305: I/Crime Lab(2409): CrimeLab.java -- in ArrayList

Snipet from Crime.java – JSONObject toJSON LOG.i is never executed

public JSONObject toJSON() throws JSONException { Log.i(TAG, "Crime.java -- in JSONObject toJSON()"); JSONObject json= new JSONObject(); json.put(JSON_ID, mId.toString()); json.put(JSON_TITLE, mTitle); json.put(JSON_SOLVED, mSolved); json.put(JSON_DATE, mDate.getTime()); Log.i(TAG, "Crime.java - JSON_ID: " + mId.toString()); Log.i(TAG, "Crime.java - JSON_TITLE: " + mTitle); Log.i(TAG, "Crime.java - JSON_SOLVED: " + mSolved); Log.i(TAG, "Crime.java - JSON_DATE: " + mDate.getTime()); return json; } // End JSONObject

End EDIT

Error listing from LogCat

03-26 11:54:27.449: E/Crime Lab(31506): Error saving crimes: 03-26 11:54:27.449: E/Crime Lab(31506): java.lang.NullPointerException 03-26 11:54:27.449: E/Crime Lab(31506): at bigdaddycoding.criminalintent.CrimeLab.saveCrimes(CrimeLab.java:54) 03-26 11:54:27.449: E/Crime Lab(31506): at bigdaddycoding.criminalintent.CrimeFragment.onPause(CrimeFragment.java:122) 03-26 11:54:27.449: E/Crime Lab(31506): at android.support.v4.app.Fragment.performPause(Fragment.java:1661) 03-26 11:54:27.449: E/Crime Lab(31506): at android.support.v4.app.FragmentManagerImpl.moveToState(FragmentManager.java:973) 03-26 11:54:27.449: E/Crime Lab(31506): at android.support.v4.app.FragmentManagerImpl.moveToState(FragmentManager.java:1104) 03-26 11:54:27.449: E/Crime Lab(31506): at android.support.v4.app.FragmentManagerImpl.moveToState(FragmentManager.java:1086) 03-26 11:54:27.449: E/Crime Lab(31506): at android.support.v4.app.FragmentManagerImpl.dispatchPause(FragmentManager.java:1898) 03-26 11:54:27.449: E/Crime Lab(31506): at android.support.v4.app.FragmentActivity.onPause(FragmentActivity.java:412) 03-26 11:54:27.449: E/Crime Lab(31506): at android.app.Activity.performPause(Activity.java:5146) 03-26 11:54:27.449: E/Crime Lab(31506): at android.app.Instrumentation.callActivityOnPause(Instrumentation.java:1240) 03-26 11:54:27.449: E/Crime Lab(31506): at android.app.ActivityThread.performPauseActivity(ActivityThread.java:2867) 03-26 11:54:27.449: E/Crime Lab(31506): at android.app.ActivityThread.performPauseActivity(ActivityThread.java:2836) 03-26 11:54:27.449: E/Crime Lab(31506): at android.app.ActivityThread.handlePauseActivity(ActivityThread.java:2814) 03-26 11:54:27.449: E/Crime Lab(31506): at android.app.ActivityThread.access$900(ActivityThread.java:139) 03-26 11:54:27.449: E/Crime Lab(31506): at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1241) 03-26 11:54:27.449: E/Crime Lab(31506): at android.os.Handler.dispatchMessage(Handler.java:99) 03-26 11:54:27.449: E/Crime Lab(31506): at android.os.Looper.loop(Looper.java:137) 03-26 11:54:27.449: E/Crime Lab(31506): at android.app.ActivityThread.main(ActivityThread.java:4918) 03-26 11:54:27.449: E/Crime Lab(31506): at java.lang.reflect.Method.invokeNative(Native Method) 03-26 11:54:27.449: E/Crime Lab(31506): at java.lang.reflect.Method.invoke(Method.java:511) 03-26 11:54:27.449: E/Crime Lab(31506): at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1004) 03-26 11:54:27.449: E/Crime Lab(31506): at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:771) 03-26 11:54:27.449: E/Crime Lab(31506): at dalvik.system.NativeStart.main(Native Method) 03-26 11:54:27.519: I/Adreno200-EGLSUB(31506): <ConfigWindowMatch:2087>: Format RGBA_8888. 03-26 11:54:27.599: D/SensorManager(31506): unregisterListener:: Listener= android.view.OrientationEventListener$SensorEventListenerImpl@42045c70 03-26 11:54:27.599: D/Sensors(31506): Remain listener = Sending .. normal delay 200ms 03-26 11:54:27.599: I/Sensors(31506): sendDelay --- 200000000 03-26 11:54:27.599: D/SensorManager(31506): JNI - sendDelay 03-26 11:54:27.599: I/SensorManager(31506): Set normal delay = true

I have looked at the code entered from the listings and do not see any errors.
Crimelab.java

[code]package bigdaddycoding.criminalintent;

import java.util.ArrayList;
import java.util.UUID;

import android.content.Context;
import android.util.Log;

public class CrimeLab {
private ArrayList mCrimes;
private static CrimeLab sCrimeLab;
private Context mAppContext;
private static final String TAG= “Crime Lab”;
private static final String FILENAME= “crimes.json”;
private CriminalIntentJSONSerializer mSerializer;

private CrimeLab(Context appContext) {
	mAppContext= appContext;
	mCrimes= new ArrayList<Crime>();
	//Commenting out the code below that used to generate 100 crimes
	//for(int i= 0; i < 100; i++) {
	//	Crime c= new Crime();
	//	c.setTitle("Crime #" + i);
	//	c.setSolved(i % 2 == 0);  // Every other one
	//	mCrimes.add(c);
	//}  //  End for
}  //  End CrimeLab

public static CrimeLab get(Context c) {
	if(sCrimeLab == null) {
		sCrimeLab= new CrimeLab(c.getApplicationContext());
	}  //  End if
	return sCrimeLab;
}  //  End CrimeLab

public void addCrime(Crime c) {
	mCrimes.add(c);
}  //  End addCrime

public ArrayList<Crime> getCrimes() {
	return mCrimes;
}  //End ArrayList<Crime>

public Crime getCrime(UUID id) {
	for(Crime c : mCrimes) {
		if(c.getId().equals(id))
			return c;
	}  //  End for
	return null;
}  //  End Crime getCrime

public boolean saveCrimes() {
	try{
		mSerializer.saveCrimes(mCrimes);
		Log.d(TAG, "Crimes saved to file");
		return true;
	}catch (Exception e) {
		Log.e(TAG, "Error saving crimes: ", e);
		return false;
	}  //  End try
}  //  End saveCrimes

} // End class CrimeLab
[/code]

Crime.java

[code]package bigdaddycoding.criminalintent;

import java.util.Date;
import java.util.UUID;

import org.json.JSONException;
import org.json.JSONObject;

public class Crime {

private UUID mId;
private String mTitle;
private Date mDate;
private boolean mSolved;
private static final String JSON_ID= "id";
private static final String JSON_TITLE= "title";
private static final String JSON_SOLVED= "solved";
private static final String JSON_DATE= "date";

public Crime() {
	//  Generate unique identifier
	mId= UUID.randomUUID();
	mDate= new Date();
	
}  //  End Crime

public JSONObject toJSON() throws JSONException {
	JSONObject json= new JSONObject();
	json.put(JSON_ID, mId.toString());
	json.put(JSON_TITLE, mTitle);
	json.put(JSON_SOLVED, mSolved);
	json.put(JSON_DATE, mDate.getTime());
	return json;
}  //  End JSONObject

@Override
public String toString() {
	return mTitle;
}  //  End String

public boolean isSolved() {
	return mSolved;
}

public void setSolved(boolean solved) {
	mSolved = solved;
}

public Date getDate() {
	return mDate;
}

public void setDate(Date date) {
	mDate = date;
}

public String getTitle() {
	return mTitle;
}

public void setTitle(String Title) {
	mTitle= Title;
}

public UUID getId() {
	return mId;
}

} // End class Crime
[/code]

CriminalIntentJSONSerializer.java

[code]package bigdaddycoding.criminalintent;

import java.io.IOException;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.io.Writer;
import java.util.ArrayList;

import org.json.JSONArray;
import org.json.JSONException;

import android.content.Context;

public class CriminalIntentJSONSerializer {

private Context mContext;
private String mFilename;

public CriminalIntentJSONSerializer(Context c, String f) {
	mContext= c;
	mFilename= f;
}  //  End CriminalIntentJSONSerializer

public void saveCrimes(ArrayList<Crime> crimes) throws JSONException, IOException {
	
	//Build an Array in JSON
	JSONArray array= new JSONArray();
	for(Crime c : crimes)
		array.put(c.toJSON());
	
	//Write the file to disk
	Writer writer= null;
	try{
		OutputStream out= mContext.openFileOutput(mFilename, Context.MODE_PRIVATE);
		writer= new OutputStreamWriter(out);
		writer.write(array.toString());
	}finally{
		if(writer != null)
			writer.close();
	}  //  End try
	
	
}  //  End saveCrimes

} // End class CriminalIntentJSONSerializer
[/code]

CrimeFragment.java

[code]package bigdaddycoding.criminalintent;

import java.util.Date;
import java.util.UUID;

import android.annotation.TargetApi;
import android.app.Activity;
import android.content.Intent;
import android.os.Build;
import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentManager;
import android.support.v4.app.NavUtils;
import android.text.Editable;
import android.text.TextWatcher;
import android.text.format.DateFormat;
import android.view.LayoutInflater;
import android.view.MenuItem;
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= "bigdaddycoding.criminalintent.crime_id";
private static final String DIALOG_DATE= "date";
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(EXTRA_CRIME_ID, crimeId);
	CrimeFragment fragment= new CrimeFragment();
	fragment.setArguments(args);
	return fragment;
}  //  End CrimeFragment

@Override
public void onCreate(Bundle savedInstanceState) {
	super.onCreate(savedInstanceState);
	UUID crimeId= (UUID)getArguments().getSerializable(EXTRA_CRIME_ID);
	mCrime= CrimeLab.get(getActivity()).getCrime(crimeId);
}  //  end onCreate Override

public void updateDate() {
	mDateButton.setText(DateFormat.format("EEEE, MMM dd, yyyy", mCrime.getDate()).toString());
}  //  End updateDate

@TargetApi(11)
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup parent, Bundle savedInstanceState) {
	View v= inflater.inflate(R.layout.fragment_crime, parent, false);
	if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB){
		if(NavUtils.getParentActivityName(getActivity()) != null) {
		getActivity().getActionBar().setDisplayHomeAsUpEnabled(true);
		}  //  End if
	}  //  End if
	mTitleField= (EditText) v.findViewById(R.id.crime_title);
	mTitleField.setText(mCrime.getTitle());
	mTitleField.addTextChangedListener(new TextWatcher() {
		public void onTextChanged(CharSequence c, int start, int before, int count) {
			mCrime.setTitle(c.toString());
		}
		public void beforeTextChanged(CharSequence c, int start, int count, int after) {
			//This is blank
		}
		public void afterTextChanged(Editable c) {
			//This is blank
		}
		
	});
	
	mDateButton= (Button) v.findViewById(R.id.crime_date);
	updateDate();
	mDateButton.setOnClickListener(new View.OnClickListener() {
		public void onClick(View v) {
			FragmentManager fm= getActivity()
					.getSupportFragmentManager();
			DatePickerFragment dialog= DatePickerFragment.newinstance(mCrime.getDate());
			dialog.setTargetFragment(CrimeFragment.this, REQUEST_DATE);
			dialog.show(fm, DIALOG_DATE);
		}  //  End onClick
	}); //  End mDateButton.setOnClickListener
	
	mSolvedCheckBox= (CheckBox) v.findViewById(R.id.crime_solved);
	mSolvedCheckBox.setChecked(mCrime.isSolved());
	mSolvedCheckBox.setOnCheckedChangeListener(new OnCheckedChangeListener() {
		public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
			//  Set the crime's solved property
			mCrime.setSolved(isChecked);
		}  //  End onCheckedChanged
	});  //  End mSolvedCheckBox.setOnCheckedChangeListener
	
	setHasOptionsMenu(true);
	return v;
}  //  end onCreateView Override

@Override
public boolean onOptionsItemSelected(MenuItem item) {
	switch(item.getItemId()) {
	case android.R.id.home:
		if(NavUtils.getParentActivityName(getActivity()) != null) {
			NavUtils.navigateUpFromSameTask(getActivity());
		}  //  End if
		return true;
		default:
			return super.onOptionsItemSelected(item);
	}  //  End switch
}  //  End onOptionsItemSelected

@Override
public void onPause() {
	super.onPause();
	CrimeLab.get(getActivity()).saveCrimes();
}  //  End onPause

@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);
		mCrime.setDate(date);
		updateDate();
	}  //  End if
}  //  End onActivityResult

} // End class CrimeFragment[/code]


#2

Not for sure why, I went on and completed the rest of the chapter and all of a sudden everything works.


#3

This problem occurs from the fact that in the constructor of CrimeLab is not create object mSerializer:

private CrimeLab(Context appContext){
        mAppContext = appContext;
        mSerializer = new CriminalIntentJSONSerializer(mAppContext, FILENAME); //need for save files
        mCrimes = new ArrayList<Crime>();

    }

this object will be created later, when data will be loading from file system.


#4

[quote=“CherepanovM”]This problem occurs from the fact that in the constructor of CrimeLab is not create object mSerializer:

private CrimeLab(Context appContext){
        mAppContext = appContext;
        mSerializer = new CriminalIntentJSONSerializer(mAppContext, FILENAME); //need for save files
        mCrimes = new ArrayList<Crime>();

    }

this object will be created later, when data will be loading from file system.[/quote]

Could you elaborate on this please? I’m receiving the same error when I apply this same save/load process on my modified version of this app.

Thanks!


#5

I have same problem and this thread fix the problem
viewtopic.php?f=414&t=6873
theres errata in listing 17.3