CheatActivity and Error


#1

I’m quite new to Android programming and I picked up several books to learn … all in all it’s been great … While working on Chptr5 of BNRG’s Android Programming, I completed and fixed all errors that appeared (truly guys you really need to update the book!) anyway, when I finally deployed the Quiz with the newly added CheatActivity I was returned an error “Unfortunately GeoQuiz has stopped”

Looking at the log I see this:

09-10 18:23:01.288: E/Trace(6562): error opening trace file: No such file or directory (2) 09-10 18:23:01.739: D/QuizActivity(6562): onCreate(Bundle) called 09-10 18:23:02.298: D/AndroidRuntime(6562): Shutting down VM 09-10 18:23:02.298: W/dalvikvm(6562): threadid=1: thread exiting with uncaught exception (group=0x40a71930) 09-10 18:23:02.318: E/AndroidRuntime(6562): FATAL EXCEPTION: main 09-10 18:23:02.318: E/AndroidRuntime(6562): java.lang.RuntimeException: Unable to start activity ComponentInfo{com.example.android.geoquiz/com.example.android.geoquiz.QuizActivity}: java.lang.NullPointerException 09-10 18:23:02.318: E/AndroidRuntime(6562): at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2180) 09-10 18:23:02.318: E/AndroidRuntime(6562): at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2230) 09-10 18:23:02.318: E/AndroidRuntime(6562): at android.app.ActivityThread.access$600(ActivityThread.java:141) 09-10 18:23:02.318: E/AndroidRuntime(6562): at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1234) 09-10 18:23:02.318: E/AndroidRuntime(6562): at android.os.Handler.dispatchMessage(Handler.java:99) 09-10 18:23:02.318: E/AndroidRuntime(6562): at android.os.Looper.loop(Looper.java:137) 09-10 18:23:02.318: E/AndroidRuntime(6562): at android.app.ActivityThread.main(ActivityThread.java:5041) 09-10 18:23:02.318: E/AndroidRuntime(6562): at java.lang.reflect.Method.invokeNative(Native Method) 09-10 18:23:02.318: E/AndroidRuntime(6562): at java.lang.reflect.Method.invoke(Method.java:511) 09-10 18:23:02.318: E/AndroidRuntime(6562): at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:793) 09-10 18:23:02.318: E/AndroidRuntime(6562): at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:560) 09-10 18:23:02.318: E/AndroidRuntime(6562): at dalvik.system.NativeStart.main(Native Method) 09-10 18:23:02.318: E/AndroidRuntime(6562): Caused by: java.lang.NullPointerException 09-10 18:23:02.318: E/AndroidRuntime(6562): at com.example.android.geoquiz.QuizActivity.onCreate(QuizActivity.java:81) 09-10 18:23:02.318: E/AndroidRuntime(6562): at android.app.Activity.performCreate(Activity.java:5104) 09-10 18:23:02.318: E/AndroidRuntime(6562): at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1080) 09-10 18:23:02.318: E/AndroidRuntime(6562): at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2144) 09-10 18:23:02.318: E/AndroidRuntime(6562): ... 11 more

To be honest with you, I can’t make heads or tails as to what happened based on this info, but I think it is due to QuizActivity (based on this line - 09-10 18:23:02.318: E/AndroidRuntime(6562): java.lang.RuntimeException: Unable to start activity ComponentInfo{com.example.android.geoquiz/com.example.android.geoquiz.QuizActivity}: java.lang.NullPointerException)

This is my CheatActivity:

[code]package com.example.android.geoquiz;

import android.app.Activity;
import android.content.Intent;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.widget.Button;
import android.widget.TextView;

public class CheatActivity extends Activity {

public static final String EXTRA_ANSWER_IS_TRUE = “com.example.android.geoquiz.answer_is_true”;
public static final String EXTRA_ANSWER_SHOWN = “com.example.android.geoquiz.answer_shown”;

private static final String TAG = “CheatActivity”;

private boolean mAnswerIsTrue;
private TextView mAnswerTextView;
private Button mShowAnswer;
private boolean mCheatButtonWasPressed;

private void setAnswerShownResult(boolean isAnswerShown) {
Intent data = new Intent();
data.putExtra(EXTRA_ANSWER_SHOWN, isAnswerShown);
setResult(RESULT_OK, data);
}

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_cheat);

  mAnswerIsTrue = getIntent().getBooleanExtra(EXTRA_ANSWER_IS_TRUE, false);
  
  mAnswerTextView = (TextView)findViewById(R.id.answerTextView);
  
    // Answer will not be shown until the user
     // presses the button
  mCheatButtonWasPressed = false;
  if (savedInstanceState != null) {
     mCheatButtonWasPressed = savedInstanceState.getBoolean(EXTRA_ANSWER_SHOWN, false);
     setAnswerShownResult(mCheatButtonWasPressed);
  } 
  else {
     setAnswerShownResult(false);
  }
  
  
  mShowAnswer = (Button)findViewById(R.id.showAnswerButton);
  mShowAnswer.setOnClickListener(new View.OnClickListener() {   
     @Override
     public void onClick(View v) {
        if (mAnswerIsTrue) {
           mAnswerTextView.setText(R.string.true_button);
        } 
        else {
           mAnswerTextView.setText(R.string.false_button);
        }
        setAnswerShownResult(true);
        mCheatButtonWasPressed = true;
     }
  });

}
//Save value after rotation
@Override
public void onSaveInstanceState(Bundle savedInstanceState) {
super.onSaveInstanceState(savedInstanceState);
Log.i(TAG, “onSaveInstanceState”);
savedInstanceState.putBoolean(EXTRA_ANSWER_SHOWN, mCheatButtonWasPressed);
}
}[/code]

And this is my QuizActivity:

[code]package com.example.android.geoquiz;

import android.content.Intent;
import android.os.Bundle;
import android.support.v7.app.ActionBarActivity;
import android.util.Log;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.widget.Button;
import android.widget.TextView;
import android.widget.Toast;

//import android.widget.*;

public class QuizActivity extends ActionBarActivity {

private static final String TAG = "QuizActivity";
private static final String KEY_INDEX = "index";

private Button mTrueButton;
private Button mFalseButton;
private Button mNextButton;
private Button mPrevButton;
private Button mCheatButton;
private TextView mQuestionTextView;

private TrueFalse[] mQuestionBank = new TrueFalse[] {
		new TrueFalse(R.string.question_oceans, true),
		new TrueFalse(R.string.question_mideast, false),
		new TrueFalse(R.string.question_africa, false),
		new TrueFalse(R.string.question_americas, true),
		new TrueFalse(R.string.question_asia, true),
};

private int mCurrentIndex = 0;

private boolean mIsCheater;

private void updateQuestion() {
	int question = mQuestionBank[mCurrentIndex].getQuestion();
	mQuestionTextView.setText(question);
}

private void checkAnswer(boolean userPressedTrue) {
	boolean answerIsTrue = mQuestionBank[mCurrentIndex].isTrueQuestion();
	
	int messageResId = 0;
	
	if (mIsCheater) {
		messageResId = R.string.judgment_toast;
	}
	else {
		if (userPressedTrue == answerIsTrue) {
			messageResId = R.string.correct_toast;
		}
		else {
			messageResId = R.string.incorrect_toast;
		}
	}
	
	Toast.makeText(this, messageResId, Toast.LENGTH_SHORT).show();
}

@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
	if (data == null) {
		return;
	}
	mIsCheater = data.getBooleanExtra(CheatActivity.EXTRA_ANSWER_SHOWN, false);
}

@Override
protected void onCreate(Bundle savedInstanceState) {
	super.onCreate(savedInstanceState);
	Log.d(TAG, "onCreate(Bundle) called");
	setContentView(R.layout.activity_quiz);
	
	//mQuestionTextView = (TextView)findViewById(R.id.question_text_view);
	/* setting for text view */
	mQuestionTextView.setOnClickListener(new View.OnClickListener() {
		@Override
		public void onClick(View v) {
			mCurrentIndex++;
			if (mCurrentIndex >= mQuestionBank.length) {
				mCurrentIndex = 0;
			}
			updateQuestion();
		}
	});
	mTrueButton = (Button)findViewById(R.id.true_button);
	mTrueButton.setOnClickListener(new View.OnClickListener() {
		@Override
		public void onClick(View v) {
			/*Toast.makeText(QuizActivity.this, R.string.incorrect_toast, Toast.LENGTH_SHORT).show();*/
			checkAnswer(true);
		}
	});
	mFalseButton = (Button)findViewById(R.id.false_button);
	mFalseButton.setOnClickListener(new View.OnClickListener() {
		@Override
		public void onClick(View v) {
			/*Toast.makeText(QuizActivity.this, R.string.correct_toast, Toast.LENGTH_SHORT).show();*/
			checkAnswer(false);
		}
	});
	mNextButton = (Button)findViewById(R.id.next_button);
	mNextButton.setOnClickListener(new View.OnClickListener() {
		@Override
		public void onClick(View v) {
			mCurrentIndex++;
			if (mCurrentIndex >= mQuestionBank.length) {
				mCurrentIndex = 0;
			}
			mIsCheater = false; /* not sure this goes here - pg.109 of Big Nerd Ranch Guide */
			updateQuestion();
		}
	});
	mPrevButton = (Button)findViewById(R.id.prev_button);
	mPrevButton.setOnClickListener(new View.OnClickListener() {
		@Override
		public void onClick(View v) {
			mCurrentIndex--;
			if (mCurrentIndex < 0) {
				mCurrentIndex = mQuestionBank.length - 1;
			}
			updateQuestion();
		}
	});
	
	if (savedInstanceState != null) {
		mCurrentIndex = savedInstanceState.getInt(KEY_INDEX, 0);
	}
	mCheatButton = (Button)findViewById(R.id.cheat_button);
	mCheatButton.setOnClickListener(new View.OnClickListener() {
		@Override
		public void onClick(View v) {
			Intent i = new Intent(QuizActivity.this, CheatActivity.class);
			boolean answerIsTrue = mQuestionBank[mCurrentIndex].isTrueQuestion();
			i.putExtra(CheatActivity.EXTRA_ANSWER_IS_TRUE, answerIsTrue);
			startActivityForResult(i, 0);
		}
	});
	updateQuestion();
	
} /* END onCreate(Bundle) */

@Override
public void onSaveInstanceState(Bundle savedInstanceState) {
	super.onSaveInstanceState(savedInstanceState);
	Log.i(TAG, "onSaveInstanceState");
	savedInstanceState.putInt(KEY_INDEX, mCurrentIndex);
}
/**/	
@Override
public void onStart() {
	super.onStart();
	Log.d(TAG, "onStart() called");
}
@Override
public void onPause() {
	super.onPause();
	Log.d(TAG, "onPause() called");
}
@Override
public void onResume() {
	super.onResume();
	Log.d(TAG, "onResume() called");
}
@Override
public void onStop() {
	super.onStop();
	Log.d(TAG, "onStop() called");
}
@Override
public void onDestroy() {
	super.onDestroy();
	Log.d(TAG, "onDestroy() called");
}
/**/


@Override
public boolean onCreateOptionsMenu(Menu menu) {
	// Inflate the menu; this adds items to the action bar if it is present.
	getMenuInflater().inflate(R.menu.quiz, menu);
	return true;
}

@Override
public boolean onOptionsItemSelected(MenuItem item) {
	// Handle action bar item clicks here. The action bar will
	// automatically handle clicks on the Home/Up button, so long
	// as you specify a parent activity in AndroidManifest.xml.
	int id = item.getItemId();
	if (id == R.id.action_settings) {
		return true;
	}
	return super.onOptionsItemSelected(item);
}

}
[/code]


#2

Um, any particular reason why you’ve commented out the line that instantiates the mQuestionTestView TextView field? The exception is occurring when you attempt to reference it and register the OnClickListener for it:

      //mQuestionTextView = (TextView)findViewById(R.id.question_text_view);
      /* setting for text view */
      mQuestionTextView.setOnClickListener(new View.OnClickListener() {...

#3

I was fixing some of the errors and debugging … looks like I forgot to un-comment that line … thanks for the extra set of eyes!