Android: execution crash when adding code SDK_INT

advertisements

I have tried to add some extra code to an already working project that would show some TextView text: a line telling the user the Android version they are using.

However, I added the code and there are no red errors in the project itself, but the app crashes when it runs. I tried to clean my project, which seems to work fine, but it doesn't fix the problem. The only files I added code to were the main, the layout, and the strings files. They are posted below. I added just 2 lines of new code in the updateQuestion() method, although it seems to have no problem there. I added a TextView widget in the activity_quiz.xml layout file (at the bottom) and then I added 1 string, <string name="api_level_text_view">API level</string> near the top in the strings.xml file.

Here is my LogCat (I don't know what it means):

01-07 00:45:18.256: E/AndroidRuntime(20543): FATAL EXCEPTION: main 01-07 00:45:18.256: E/AndroidRuntime(20543): java.lang.RuntimeException: Unable to start activity ComponentInfo{com.bignerdranch.android.geoquiz/com.bignerdranch.android.geoquiz.QuizActivity}: java.lang.NullPointerException 01-07 00:45:18.256: E/AndroidRuntime(20543): at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2211) 01-07 00:45:18.256: E/AndroidRuntime(20543): at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2261) 01-07 00:45:18.256: E/AndroidRuntime(20543): at android.app.ActivityThread.access$600(ActivityThread.java:141) 01-07 00:45:18.256: E/AndroidRuntime(20543): at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1256) 01-07 00:45:18.256: E/AndroidRuntime(20543): at android.os.Handler.dispatchMessage(Handler.java:99) 01-07 00:45:18.256: E/AndroidRuntime(20543): at android.os.Looper.loop(Looper.java:137) 01-07 00:45:18.256: E/AndroidRuntime(20543): at android.app.ActivityThread.main(ActivityThread.java:5103) 01-07 00:45:18.256: E/AndroidRuntime(20543): at java.lang.reflect.Method.invokeNative(Native Method) 01-07 00:45:18.256: E/AndroidRuntime(20543): at java.lang.reflect.Method.invoke(Method.java:525) 01-07 00:45:18.256: E/AndroidRuntime(20543): at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:737) 01-07 00:45:18.256: E/AndroidRuntime(20543): at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:553) 01-07 00:45:18.256: E/AndroidRuntime(20543): at dalvik.system.NativeStart.main(Native Method) 01-07 00:45:18.256: E/AndroidRuntime(20543): Caused by: java.lang.NullPointerException 01-07 00:45:18.256: E/AndroidRuntime(20543): at com.bignerdranch.android.geoquiz.QuizActivity.updateQuestion(QuizActivity.java:55) 01-07 00:45:18.256: E/AndroidRuntime(20543): at com.bignerdranch.android.geoquiz.QuizActivity.onCreate(QuizActivity.java:167) 01-07 00:45:18.256: E/AndroidRuntime(20543): at android.app.Activity.performCreate(Activity.java:5133) 01-07 00:45:18.256: E/AndroidRuntime(20543): at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1087) 01-07 00:45:18.256: E/AndroidRuntime(20543): at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2175) 01-07 00:45:18.256: E/AndroidRuntime(20543): ... 11 more

Here is my QuizActivity.java (main) file:

package com.bignerdranch.android.geoquiz;

import android.annotation.TargetApi;
import android.app.ActionBar;
import android.app.Activity;
import android.content.Intent;
import android.os.Build;
import android.os.Bundle;
import android.util.Log;
import android.view.Menu;
import android.view.View;
import android.widget.Button;
import android.widget.ImageButton;
import android.widget.TextView;
import android.widget.Toast;

public class QuizActivity extends Activity {

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

    private Button mTrueButton;
    private Button mFalseButton;
    private ImageButton mPrevButton;
    private ImageButton mNextButton;
    private Button mCheatButton;
    private TextView mQuestionTextView;
    private boolean mIsCheater;
    private boolean mCheater;
    private static final String IS_CHEATER = "false";
    private static final String TAG1 = "CheatActivity";

    private TextView mApiLevelTextView;
    private String mApiLevel;

    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;

    public void updateQuestion() {

        int question = mQuestionBank[mCurrentIndex].getQuestion();
        mQuestionTextView.setText(question);

        mApiLevel = (getString(R.string.api_level_text_view) + " " + Build.VERSION.SDK_INT);
        mApiLevelTextView.setText(mApiLevel);

    }

    private void checkAnswer(boolean userPressedTrue) {
        boolean answerIsTrue = mQuestionBank[mCurrentIndex].isTrueQuestion();

        int messageResId = 0;

    if (mIsCheater) if (userPressedTrue == answerIsTrue) {
        messageResId = R.string.judgment_toast;
    } else {
        messageResId = R.string.incorrect_judgement_toast;
    } else {

        if (userPressedTrue == answerIsTrue) {
            messageResId = R.string.correct_toast;
        }
        else {
            messageResId = R.string.incorrect_toast;
        }
    }

        Toast.makeText(this, messageResId, Toast.LENGTH_SHORT).show();
    }

    @TargetApi(11)
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        Log.d(TAG, "onCreate() called");
        setContentView(R.layout.activity_quiz);

        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) {
            ActionBar actionBar = getActionBar();
            actionBar.setSubtitle("Bodies of Water");
        }

        mCheater = false;
        if (savedInstanceState != null) {
           mCheater = savedInstanceState.getBoolean(IS_CHEATER, false);
        }

        mQuestionTextView = (TextView)findViewById(R.id.question_text_view);
        mQuestionTextView.setOnClickListener(new View.OnClickListener(){
            @Override
            public void onClick(View v) {
                mCurrentIndex = (mCurrentIndex + 1) % mQuestionBank.length;

                updateQuestion();
            }

        });

        mTrueButton = (Button)findViewById(R.id.true_button);
        mTrueButton.setOnClickListener(new View.OnClickListener() {

            @Override
            public void onClick(View v) {
                checkAnswer(true);
            }
        });

        mFalseButton = (Button)findViewById(R.id.false_button);
        mFalseButton.setOnClickListener(new View.OnClickListener() {

            @Override
            public void onClick(View v) {
                checkAnswer(false);
            }
        });

        mPrevButton = (ImageButton)findViewById(R.id.prev_button);
        mPrevButton.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                int length = mQuestionBank.length;
                   mCurrentIndex = (mCurrentIndex + (length-1)) % length;

                updateQuestion();
            }
        });

        mNextButton = (ImageButton)findViewById(R.id.next_button);
        mNextButton.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                mCurrentIndex = (mCurrentIndex + 1) % mQuestionBank.length;
                mIsCheater = false;
                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();

    }
    //onCreate Bundle ends

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

    @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;
    }

}

Here is my layout file:

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:gravity="center"
    android:orientation="vertical" >

    <TextView
        android:id="@+id/question_text_view"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:padding="24dp" />        

    <LinearLayout
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:orientation="horizontal" >

        <Button
            android:id="@+id/true_button"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="@string/true_button" />

        <Button
            android:id="@+id/false_button"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="@string/false_button" />

    </LinearLayout>

    <Button
        android:id="@+id/cheat_button"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="@string/cheat_button" />

    <LinearLayout
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:orientation="horizontal" >

        <ImageButton
        android:id="@+id/prev_button"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:src="@drawable/arrow_left"
        android:contentDescription="@string/move_back"
         />

        <ImageButton
        android:id="@+id/next_button"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:src="@drawable/arrow_right"
        android:contentDescription="@string/move_forward"
        />

    <TextView
        android:id="@+id/api_level_text_view"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:textAllCaps="true"
        android:paddingTop="40sp"
        android:textSize="20sp" />

    </LinearLayout>

</LinearLayout>

Here is my strings.xml file:

<?xml version="1.0" encoding="utf-8"?>
<resources>

    <string name="app_name">GeoQuiz</string>
    <string name="api_level_text_view">API level</string>

    <string name="true_button">True</string>
    <string name="false_button">False</string>
    <string name="prev_button">Prev</string>
    <string name="move_back">Move back</string>
    <string name="next_button">Next</string>
    <string name="move_forward">Move forward</string>

    <string name="correct_toast">Correct!</string>
    <string name="incorrect_toast">Incorrect!</string>

    <string name="action_settings">Settings</string>
    <string name="question_oceans">The Pacific Ocean is larger than the Atlantic Ocean</string>
    <string name="question_mideast">The Suez Canal connects the Red Sea and the Indian Ocean.</string>
    <string name="question_africa">The source of the Nile River is in Egypt.</string>
    <string name="question_americas">The Amazon River is the longest river in the Americas.</string>
    <string name="question_asia">Lake Baikal is the world\'s oldest and deepest freshwater lake.</string>

    <string name="cheat_button">Cheat!</string>
    <string name="warning_text">Are you sure you want to do this?</string>
    <string name="show_answer_button">Show Answer</string>
    <string name="judgment_toast">Cheating is wrong.</string>
    <string name="incorrect_judgement_toast">You do not cheat very well. \nStick to guessing.</string>

</resources>


You forgot to initialize mApiLevelTextView.

Add

mApiLevelTextView = (TextView)findViewById(R.id.api_level_text_view);

somewhere between setContentView() and where you're using mApiLevelTextView.