Nullpointer after loading file


#1

Hello! First time poster, and I’ve gone through chapter 17, and whenever i run the app after having saved a file it instantly crashes. I added a LOG to check if mCrimes is null in CrimesListFragment, and it shows the crimes that I saved prior, however it crashes and won’t continue to show the List of crimes.
This is my first post ever so i don’t know if this is too much… but i have been stuck on this for a few days and i’m a complete noob to android. All chapters and even the challenges worked perfectly so far except for this chapter (the 1 i want to learn the most -.-).

I would appreciate any help!

Here are the classes:

Here is the CrimeLab.java class

[code]package com.jeedan.android.criminalintent;

import java.util.ArrayList;
import java.util.UUID;
import android.content.Context;
import android.util.Log;

public class CrimeLab {

private static final String TAG = "CrimeLab";
private static final String FILENAME = "comeon.json";

private ArrayList<Crime> mCrimes;
private CriminalIntentJSONSerializer mSerializer;

private static CrimeLab sCrimeLab; // singleton
private Context mAppContext;

private CrimeLab(Context appContext){
	mAppContext = appContext;
	mSerializer = new CriminalIntentJSONSerializer(mAppContext, FILENAME); // create a serializer that we will use to save and load files

	//mCrimes = new ArrayList<Crime>();
	try {
		mCrimes = mSerializer.loadCrimesOLD();
		Log.d(TAG, "crimes loaded");
	} catch (Exception e) {
		mCrimes = new ArrayList<Crime>();
		Log.e(TAG, "Error loading crimes: ", e);
	}
	//load();
}

public void load(){
	try {
		//mCrimes = mSerializer.loadCrimes();
	} catch (Exception e) {
		mCrimes = new ArrayList<Crime>();
		Log.e(TAG, "Error loading crimes: ", e);
	}
}

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

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

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

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

public Crime getCrime(UUID id){
	for(Crime c : mCrimes){
		if(c.getID().equals(id))
			return c;
	}
	return null; // return null if the crime id does not exist or equal to the specified id
}

}
[/code]

Here is the CriminalIntentJSONSerializer.java class

package com.jeedan.android.criminalintent;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
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 org.json.JSONTokener;

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

public class CriminalIntentJSONSerializer {
	private static final String TAG = "CriminalIntentJSONSerializer";
	private Context mContext;
	private String mFilename;
	private File mFile;
	
	public CriminalIntentJSONSerializer(Context context, String fileName){
		mContext = context;
		mFilename = fileName;
	}
	

    public ArrayList<Crime> loadCrimesOLD() throws IOException, JSONException {
        ArrayList<Crime> crimes = new ArrayList<Crime>();
        BufferedReader reader = null;
        try {
            // open and read the file into a StringBuilder
            InputStream in = mContext.openFileInput(mFilename);
            reader = new BufferedReader(new InputStreamReader(in));
            StringBuilder jsonString = new StringBuilder();
            String line = null;
            while ((line = reader.readLine()) != null) {
                // line breaks are omitted and irrelevant
                jsonString.append(line);
            }
            // parse the JSON using JSONTokener
            JSONArray array = (JSONArray) new JSONTokener(jsonString.toString()).nextValue();
            // build the array of crimes from JSONObjects
            for (int i = 0; i < array.length(); i++) {
                crimes.add(new Crime(array.getJSONObject(i)));
            }
        } catch (FileNotFoundException e) {
            // we will ignore this one, since it happens when we start fresh
        } finally {
            if (reader != null)
                reader.close();
            }

        return crimes;
    }

    public void saveCrimesOLD(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();
        }
    }
}

Here is the CrimeListFragment.java class

[code]package com.jeedan.android.criminalintent;

import java.util.ArrayList;
import android.annotation.TargetApi;
import android.content.Intent;
import android.os.AsyncTask;
import android.os.Build;
import android.os.Bundle;
import android.support.v4.app.ListFragment;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.ViewGroup;
import android.widget.ArrayAdapter;
import android.widget.Button;
import android.widget.CheckBox;
import android.widget.ListView;
import android.widget.TextView;

public class CrimeListFragment extends ListFragment {
private static final String TAG = “CrimeListFragment”;
private ArrayList mCrimes;
private boolean mSubtitleVisible;

private Button mAddNewCrimeButton;
@Override
public void onCreate(Bundle savedInstanceState){
	super.onCreate(savedInstanceState);

	setHasOptionsMenu(true);
	
	
	getActivity().setTitle(R.string.crimes_title);
	
	Log.d(TAG, "started onCreate()");
	// get crimes

	mCrimes = CrimeLab.get(getActivity()).getCrimes();
	Log.e(TAG, mCrimes.toString());
	
	// set up the adapter to display list view
	//ArrayAdapter<Crime> adapter = new ArrayAdapter(getActivity(), android.R.layout.simple_list_item_1, mCrimes);
	CrimeAdapter adapter = new CrimeAdapter(mCrimes);
	setListAdapter(adapter); // let the listfragment know that adapter will be the 1 we get from "getListAdapter()
	setRetainInstance(true);
	mSubtitleVisible = true;
}
@TargetApi(11)
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup parent, Bundle savedInstanceState){
	//View v = super.onCreateView(inflater, parent, savedInstanceState);
	View v = inflater.inflate(R.layout.fragment_list_view_crimes, parent, false);

	if(getListAdapter().isEmpty()){
		//v = inflater.inflate(R.layout.fragment_list_empty, parent, false);
		mAddNewCrimeButton = (Button)v.findViewById(R.id.add_crime_button);
		mAddNewCrimeButton.setOnClickListener(new OnClickListener() {
			
			@Override
			public void onClick(View v) {
				// TODO Auto-generated method stub
				addNewCrime();
			}
		});
	}
	if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB){
		if(mSubtitleVisible){
			getActivity().getActionBar().setSubtitle(R.string.subtitle);
		}
	}	
	return v;
}

@Override
public void onResume(){
	super.onResume();
	((CrimeAdapter)getListAdapter()).notifyDataSetChanged();
}

@Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
    ((CrimeAdapter)getListAdapter()).notifyDataSetChanged();
}

@Override
public void onListItemClick(ListView l, View v, int position, long id){
	Crime c = ((CrimeAdapter)getListAdapter()).getItem(position);
	// start a crime activity
	Intent crimeActivityIntent = new Intent(getActivity(), CrimePagerActivity.class);
	crimeActivityIntent.putExtra(CrimeFragment.EXTRA_CRIME_ID, c.getID());
	startActivity(crimeActivityIntent);
}

@Override
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater){
	super.onCreateOptionsMenu(menu, inflater);
	inflater.inflate(R.menu.fragment_crime_list, menu);
	MenuItem showSubtitle = menu.findItem(R.id.menu_item_show_subtitle);
	if(mSubtitleVisible && showSubtitle != null){
		showSubtitle.setTitle(R.string.hide_subtitle);
	}
}

@TargetApi(11)
@Override
public boolean onOptionsItemSelected(MenuItem item){
	switch (item.getItemId()) {
	case R.id.menu_item_new_crime:
		addNewCrime();
		return true;
	case R.id.menu_item_show_subtitle:
		if(getActivity().getActionBar().getSubtitle() == null){
			getActivity().getActionBar().setSubtitle(R.string.subtitle);
			mSubtitleVisible = true;
			item.setTitle(R.string.hide_subtitle);
		}else {
			getActivity().getActionBar().setSubtitle(null);
			mSubtitleVisible = false;
			item.setTitle(R.string.show_subtitle);
		}
		return true;
	default:
		return super.onOptionsItemSelected(item);
	}
}

private void addNewCrime(){
	Crime crime = new Crime();
	CrimeLab.get(getActivity()).addCrime(crime);	
	Intent i = new Intent(getActivity(), CrimePagerActivity.class);
	i.putExtra(CrimeFragment.EXTRA_CRIME_ID, crime.getID());
	startActivityForResult(i,0);
}

private class CrimeAdapter extends ArrayAdapter<Crime>{
	public CrimeAdapter(ArrayList<Crime> crimes ){
		super(getActivity(), 0, crimes);
	}
	
	@Override
	public View getView(int position, View convertView, ViewGroup parent){
		// if we weren't given a view, inflate one
		if(convertView == null)
			convertView = getActivity().getLayoutInflater().inflate(R.layout.list_item_crime, null);
		
		// Configure the view for this Crime 
		Crime c = getItem(position);
		
		TextView titleTextView = (TextView)convertView.findViewById(R.id.crime_list_item_titleTextView);
		titleTextView.setText(c.getTitle());

		TextView dateTextView = (TextView)convertView.findViewById(R.id.crime_list_item_titleDateTextView);
		dateTextView.setText(c.getFormatedDate());
		
		CheckBox solvedCheckBox = (CheckBox)convertView.findViewById(R.id.crime_list_item_solvedCheckBox);
		solvedCheckBox.setChecked(c.isSolved());
		return convertView;
	}
}

}
[/code]

The error 10-24 15:47:04.292: E/CrimeListFragment(22061): [tutu] 10-24 15:47:04.322: E/AndroidRuntime(22061): FATAL EXCEPTION: main 10-24 15:47:04.322: E/AndroidRuntime(22061): Process: com.jeedan.android.criminalintent, PID: 22061 10-24 15:47:04.322: E/AndroidRuntime(22061): java.lang.NullPointerException 10-24 15:47:04.322: E/AndroidRuntime(22061): at com.jeedan.android.criminalintent.Crime.getFormatedDate(Crime.java:57) 10-24 15:47:04.322: E/AndroidRuntime(22061): at com.jeedan.android.criminalintent.CrimeListFragment$CrimeAdapter.getView(CrimeListFragment.java:157) 10-24 15:47:04.322: E/AndroidRuntime(22061): at android.widget.AbsListView.obtainView(AbsListView.java:2255) 10-24 15:47:04.322: E/AndroidRuntime(22061): at android.widget.ListView.measureHeightOfChildren(ListView.java:1263) 10-24 15:47:04.322: E/AndroidRuntime(22061): at android.widget.ListView.onMeasure(ListView.java:1175) 10-24 15:47:04.322: E/AndroidRuntime(22061): at android.view.View.measure(View.java:16497) 10-24 15:47:04.322: E/AndroidRuntime(22061): at android.view.ViewGroup.measureChildWithMargins(ViewGroup.java:5125) 10-24 15:47:04.322: E/AndroidRuntime(22061): at android.widget.FrameLayout.onMeasure(FrameLayout.java:310) 10-24 15:47:04.322: E/AndroidRuntime(22061): at android.view.View.measure(View.java:16497) 10-24 15:47:04.322: E/AndroidRuntime(22061): at android.view.ViewGroup.measureChildWithMargins(ViewGroup.java:5125) 10-24 15:47:04.322: E/AndroidRuntime(22061): at android.widget.FrameLayout.onMeasure(FrameLayout.java:310) 10-24 15:47:04.322: E/AndroidRuntime(22061): at android.view.View.measure(View.java:16497) 10-24 15:47:04.322: E/AndroidRuntime(22061): at android.view.ViewGroup.measureChildWithMargins(ViewGroup.java:5125) 10-24 15:47:04.322: E/AndroidRuntime(22061): at android.widget.FrameLayout.onMeasure(FrameLayout.java:310) 10-24 15:47:04.322: E/AndroidRuntime(22061): at android.view.View.measure(View.java:16497) 10-24 15:47:04.322: E/AndroidRuntime(22061): at android.view.ViewGroup.measureChildWithMargins(ViewGroup.java:5125) 10-24 15:47:04.322: E/AndroidRuntime(22061): at android.widget.FrameLayout.onMeasure(FrameLayout.java:310) 10-24 15:47:04.322: E/AndroidRuntime(22061): at android.view.View.measure(View.java:16497) 10-24 15:47:04.322: E/AndroidRuntime(22061): at android.view.ViewGroup.measureChildWithMargins(ViewGroup.java:5125) 10-24 15:47:04.322: E/AndroidRuntime(22061): at com.android.internal.widget.ActionBarOverlayLayout.onMeasure(ActionBarOverlayLayout.java:327) 10-24 15:47:04.322: E/AndroidRuntime(22061): at android.view.View.measure(View.java:16497) 10-24 15:47:04.322: E/AndroidRuntime(22061): at android.view.ViewGroup.measureChildWithMargins(ViewGroup.java:5125) 10-24 15:47:04.322: E/AndroidRuntime(22061): at android.widget.FrameLayout.onMeasure(FrameLayout.java:310) 10-24 15:47:04.322: E/AndroidRuntime(22061): at com.android.internal.policy.impl.PhoneWindow$DecorView.onMeasure(PhoneWindow.java:2291) 10-24 15:47:04.322: E/AndroidRuntime(22061): at android.view.View.measure(View.java:16497) 10-24 15:47:04.322: E/AndroidRuntime(22061): at android.view.ViewRootImpl.performMeasure(ViewRootImpl.java:1912) 10-24 15:47:04.322: E/AndroidRuntime(22061): at android.view.ViewRootImpl.measureHierarchy(ViewRootImpl.java:1109) 10-24 15:47:04.322: E/AndroidRuntime(22061): at android.view.ViewRootImpl.performTraversals(ViewRootImpl.java:1291) 10-24 15:47:04.322: E/AndroidRuntime(22061): at android.view.ViewRootImpl.doTraversal(ViewRootImpl.java:996) 10-24 15:47:04.322: E/AndroidRuntime(22061): at android.view.ViewRootImpl$TraversalRunnable.run(ViewRootImpl.java:5600) 10-24 15:47:04.322: E/AndroidRuntime(22061): at android.view.Choreographer$CallbackRecord.run(Choreographer.java:761) 10-24 15:47:04.322: E/AndroidRuntime(22061): at android.view.Choreographer.doCallbacks(Choreographer.java:574) 10-24 15:47:04.322: E/AndroidRuntime(22061): at android.view.Choreographer.doFrame(Choreographer.java:544) 10-24 15:47:04.322: E/AndroidRuntime(22061): at android.view.Choreographer$FrameDisplayEventReceiver.run(Choreographer.java:747) 10-24 15:47:04.322: E/AndroidRuntime(22061): at android.os.Handler.handleCallback(Handler.java:733) 10-24 15:47:04.322: E/AndroidRuntime(22061): at android.os.Handler.dispatchMessage(Handler.java:95) 10-24 15:47:04.322: E/AndroidRuntime(22061): at android.os.Looper.loop(Looper.java:136) 10-24 15:47:04.322: E/AndroidRuntime(22061): at android.app.ActivityThread.main(ActivityThread.java:5001) 10-24 15:47:04.322: E/AndroidRuntime(22061): at java.lang.reflect.Method.invokeNative(Native Method) 10-24 15:47:04.322: E/AndroidRuntime(22061): at java.lang.reflect.Method.invoke(Method.java:515) 10-24 15:47:04.322: E/AndroidRuntime(22061): at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:785) 10-24 15:47:04.322: E/AndroidRuntime(22061): at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:601) 10-24 15:47:04.322: E/AndroidRuntime(22061): at dalvik.system.NativeStart.main(Native Method)


#2

nevermind i am retarded…

in the error “Formatted date” is null and crashes the program, as we do not create that in the JSON file, we save an unformatted date…