Welcome to the Treehouse Community

The Treehouse Community is a meeting place for developers, designers, and programmers of all backgrounds and skill levels to get support. Collaborate here on code errors or bugs that you need feedback on, or asking for an extra set of eyes on your latest project. Join thousands of Treehouse students and alumni in the community today. (Note: Only Treehouse students can comment or ask questions, but non-students are welcome to browse our conversations.)

Looking to learn something new?

Treehouse offers a seven day free trial for new students. Get access to thousands of hours of content and a supportive community. Start your free trial today.

Android Build an Interactive Story App (Retired) Finishing the User Interface Ending the Story

Adewale Adeyinka
Adewale Adeyinka
2,026 Points

I am still getting a null pointer exception.

10-31 14:10:19.159 13238-13238/cs.interactivestory E/AndroidRuntime: FATAL EXCEPTION: main 10-31 14:10:19.159 13238-13238/cs.interactivestory E/AndroidRuntime: Process: cs.interactivestory, PID: 13238 10-31 14:10:19.159 13238-13238/cs.interactivestory E/AndroidRuntime: java.lang.NullPointerException: Attempt to invoke virtual method 'java.lang.String cs.interactivestory.model.Choice.getText()' on a null object reference 10-31 14:10:19.159 13238-13238/cs.interactivestory E/AndroidRuntime: at cs.interactivestory.ui.StoryActivity.loadPage(StoryActivity.java:80) 10-31 14:10:19.159 13238-13238/cs.interactivestory E/AndroidRuntime: at cs.interactivestory.ui.StoryActivity.access$100(StoryActivity.java:18) 10-31 14:10:19.159 13238-13238/cs.interactivestory E/AndroidRuntime: at cs.interactivestory.ui.StoryActivity$3.onClick(StoryActivity.java:97) 10-31 14:10:19.159 13238-13238/cs.interactivestory E/AndroidRuntime: at

AND HERE IS MY CODE:

  if (mCurrentPage.isFinal()) {
        mChoice1.setVisibility(View.INVISIBLE);
        mChoice2.setText("PLAY AGAIN");
        mChoice2.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                finish();
            }
        });
    }
    else {

        mChoice1.setText(mCurrentPage.getChoice1().getText());
        mChoice2.setText(mCurrentPage.getChoice2().getText());

        mChoice1.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {

                int nextPage = mCurrentPage.getChoice1().getNextPage();
                loadPage(nextPage);
            }
        });

        mChoice2.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {

                int nextPage = mCurrentPage.getChoice2().getNextPage();
                loadPage(nextPage);
            }
        });
    }
}
Vrezh Gulyan
Vrezh Gulyan
11,161 Points

Looks like you might've forgotten to initialize either mChoice1 or mChoice2 since the error you're getting basically says that you are referencing something that has no value or null.

private Button mChoice1;
private Button mChoice2;

mChoice1 = (Button)findViewById(R.id.choiceButton1);
mChoice2 = (Button)findViewById(R.id.choiceButton2);

Double check if you have this in your code before you call the final method, if this wasn't the problem then post your entire code and I'll help you find the bug.

Adewale Adeyinka
Adewale Adeyinka
2,026 Points

Thanks for the response Vrezh, I have checked and both variables have been intialised. Here is my full code:

public class StoryActivity extends AppCompatActivity {
public static final String TAG = StoryActivity.class.getSimpleName();
private Story mStory = new Story();
private ImageView mImageView;
private TextView mTextView;
private Button mChoice1;
private Button mChoice2;
private String mName;
private Page mCurrentPage;

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

    Intent intent = getIntent();
     mName = intent.getStringExtra(getString(R.string.key_name));

    //to stop us from getting a null pointer exception
    if (mName == null){

        mName = "Friend";
    }
    Log.d(TAG,mName);

    mImageView = (ImageView) findViewById(R.id.storyImageView);
    mTextView = (TextView) findViewById(R.id.storyTextView);
    mChoice1 = (Button) findViewById(R.id.choiceButton1);
    mChoice2 = (Button) findViewById(R.id.choiceButton2);

    loadPage (0);

}

private void loadPage (int choice){

     mCurrentPage = mStory.getPage(choice);

    Drawable drawable = ContextCompat.getDrawable(this, mCurrentPage.getImageId());
    mImageView.setImageDrawable(drawable);
    String pageText = mCurrentPage.getText();
    //This will add the name if placeholder included. Won't add it if no placeholder.

    pageText = String.format(pageText,mName);
    mTextView.setText(pageText);

    if (mCurrentPage.isFinal()) {
        mChoice1.setVisibility(View.INVISIBLE);
        mChoice2.setText("PLAY AGAIN");
        mChoice2.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                finish();
            }
        });
    }
    else {

        mChoice1.setText(mCurrentPage.getChoice1().getText());
        mChoice2.setText(mCurrentPage.getChoice2().getText());

        mChoice1.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {

                int nextPage = mCurrentPage.getChoice1().getNextPage();
                loadPage(nextPage);
            }
        });

        mChoice2.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {

                int nextPage = mCurrentPage.getChoice2().getNextPage();
                loadPage(nextPage);
            }
        });
    }
  }
 }

4 Answers

Wezen Design
Wezen Design
1,460 Points

It's possible that you have forgotten to set the variable mIsFinal=true in the second constructor in Page class.

public Page(int imageId, String text){ mImageId = imageId; mText = text; mChoice1 = null; mChoice2 = null; mIsFinal = true; }

Adewale Adeyinka
Adewale Adeyinka
2,026 Points

Thank you very much, you were right! I have been trying to solve this issue for weeks...at last.

Vrezh Gulyan
Vrezh Gulyan
11,161 Points

I used your StoryActivity class in my app and it worked perfectly... When do you get an error? In what scenario? When the name is left blank? Also post your MainActivity if you dont mind.

Adewale Adeyinka
Adewale Adeyinka
2,026 Points

Yeah sorry I should have mentioned where it was exactly I was getting the error. I get an error when I click on "CONTINUE TOWARDS THE FAINT LIGHT" and the error says "Unfortunately, interactive story has stopped". Its meant to take me to the last page where it says "PLAY AGAIN" but it doesn't, here is my main activity class:

    public class MainActivity extends AppCompatActivity {
    private EditText mNameField;
    private Button mStartButton;

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

        mNameField = (EditText) findViewById(R.id.nameEditText);
        mStartButton = (Button) findViewById(R.id.startButton);

        mStartButton.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {

                String name = mNameField.getText().toString();
                startStory(name);

            }
        });
    }

    private void startStory(String name){
        Intent intent = new Intent(this, StoryActivity.class);
        intent.putExtra(getString(R.string.key_name),name);
        startActivity(intent);
    }
   }
Vrezh Gulyan
Vrezh Gulyan
11,161 Points

Your mainActivity and your storyActivity are both fine and work with my application, which only leaves the possibility that there must be a type in your story, page or choice class. I posted my story class below compare them side by side to see if you see a mistake, I am guessing that the error will be in mPages[4]

public class Story {
    private Page[] mPages;

    public Story(){
        mPages = new Page[7];
    mPages[0] = new Page(
            R.drawable.page0,
            "On your return trip from studying Saturn's rings, you hear a distress signal that seems to be coming from the surface of Mars. It's strange because there hasn't been a colony there in years. Even stranger, it's calling you by name: \"Help me, %1$s, you're my only hope.\"",
            new Choice("Stop and investigate", 1),
            new Choice("Continue home to Earth", 2));

    mPages[1] = new Page(
            R.drawable.page1,
            "You deftly land your ship near where the distress signal originated. You didn't notice anything strange on your fly-by, but there is a cave in front of you. Behind you is an abandoned rover from the early 21st century.",
            new Choice("Explore the cave", 3),
            new Choice("Explore the rover", 4));

    mPages[2] = new Page(
            R.drawable.page2,
            "You continue your course to Earth. Two days later, you receive a transmission from HQ saying that they have detected some sort of anomaly on the surface of Mars near an abandoned rover. They ask you to investigate, but ultimately the decision is yours because your mission has already run much longer than planned and supplies are low.",
            new Choice("Head back to Mars to investigate", 4),
            new Choice("Continue home to Earth", 6));

    mPages[3] = new Page(
            R.drawable.page3,
            "Your EVA suit is equipped with a headlamp, which you use to navigate the cave. After searching for a while your oxygen levels are starting to get pretty low. You know you should go refill your tank, but there's a very faint light up ahead.",
            new Choice("Refill at ship and explore the rover", 4),
            new Choice("Continue towards the faint light", 5));

    mPages[4] = new Page(
            R.drawable.page4,
            "The rover is covered in dust and most of the solar panels are broken. But you are quite surprised to see the on-board system booted up and running. In fact, there is a message on the screen: \"%1$s, come to 28.543436, -81.369031.\" Those coordinates aren't far, but you don't know if your oxygen will last there and back.",
            new Choice("Explore the coordinates", 5),
            new Choice("Return to Earth", 6));

    mPages[5] = new Page(
            R.drawable.page5,
            "After a long walk slightly uphill, you end up at the top of a small crater. You look around, and are overjoyed to see your favorite android, %1$s-S1124. It had been lost on a previous mission to Mars! You take it back to your ship and fly back to Earth.");
    mPages[6] = new Page(
            R.drawable.page6,
            "You arrive home on Earth. While your mission was a success, you forever wonder what was sending that signal. Perhaps a future mission will be able to investigate...");
}

    public Page getPage(int pageNumber){
        return mPages[pageNumber];
    }

}
Adewale Adeyinka
Adewale Adeyinka
2,026 Points

Thanks but its exactly same as yours:

public class Story {

    private Page[] mPages;

    public Story (){

        mPages = new Page[7];

        mPages[0] = new Page(
                R.mipmap.page0,
                "On your return trip from studying Saturn's rings, you hear a distress signal that seems to be coming from the surface of Mars. It's strange because there hasn't been a colony there in years. Even stranger, it's calling you by name: \"Help me, %1$s, you're my only hope.\"",
                new Choice("Stop and investigate", 1),
                new Choice("Continue home to Earth", 2));

        mPages[1] = new Page(
                R.mipmap.page1,
                "You deftly land your ship near where the distress signal originated. You didn't notice anything strange on your fly-by, but there is a cave in front of you. Behind you is an abandoned rover from the early 21st century.",
                new Choice("Explore the cave", 3),
                new Choice("Explore the rover", 4));

        mPages[2] = new Page(
                R.mipmap.page2,
                "You continue your course to Earth. Two days later, you receive a transmission from HQ saying that they have detected some sort of anomaly on the surface of Mars near an abandoned rover. They ask you to investigate, but ultimately the decision is yours because your mission has already run much longer than planned and supplies are low.",
                new Choice("Head back to Mars to investigate", 4),
                new Choice("Continue home to Earth", 6));

        mPages[3] = new Page(
                R.mipmap.page3,
                "Your EVA suit is equipped with a headlamp, which you use to navigate the cave. After searching for a while your oxygen levels are starting to get pretty low. You know you should go refill your tank, but there's a very faint light up ahead.",
                new Choice("Refill at ship and explore the rover", 4),
                new Choice("Continue towards the faint light", 5));

        mPages[4] = new Page(
                R.mipmap.page4,
                "The rover is covered in dust and most of the solar panels are broken. But you are quite surprised to see the on-board system booted up and running. In fact, there is a message on the screen: \"%1$s, come to 28.543436, -81.369031.\" Those coordinates aren't far, but you don't know if your oxygen will last there and back.",
                new Choice("Explore the coordinates", 5),
                new Choice("Return to Earth", 6));

        mPages[5] = new Page(
                R.mipmap.page5,
                "After a long walk slightly uphill, you end up at the top of a small crater. You look around, and are overjoyed to see your favorite android, %1$s-S1124. It had been lost on a previous mission to Mars! You take it back to your ship and fly back to Earth.");

        mPages[6] = new Page(
                R.mipmap.page6,
                "You arrive home on Earth. While your mission was a success, you forever wonder what was sending that signal. Perhaps a future mission will be able to investigate...");
    }

        public Page getPage (int pageNumber){

            return mPages[pageNumber];
        }

    }
HARSH TYAGI
PLUS
HARSH TYAGI
Courses Plus Student 1,535 Points

Hey, I was getting the same error and it boggled my mind since I wasn't able to debug it. Instead, I modified my code a little bit. I did not use the second constructor of the page class and passed a blank string and '0'index value in the page 5 and 6 of the Story class. Also instead of checking the isfinal() method, I created another method in the StoryActivity with same content (making the button invisible and using finish function), then I called the function above. Now it works perfectly fine. though it is a different logic , but I think there wasn't much difference in the complexity. if you want I can give you my code. :)