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

Andreas Robichaux
Andreas Robichaux
2,426 Points

Interactive Story App is crashing after i enter the cadet name...

I ran it in debug mode and this is what i got. It loads fine but as soon as you click start your adventure it crashes.

05-06 20:58:27.361    2276-2293/dredaydesigns.interactivestory D/OpenGLRenderer Render dirty regions requested: true
05-06 20:58:27.365    2276-2276/dredaydesigns.interactivestory D/ HostConnection::get() New Host Connection established 0xa6659980, tid 2276
05-06 20:58:27.445    2276-2276/dredaydesigns.interactivestory D/Atlas Validating map...
05-06 20:58:27.518    2276-2293/dredaydesigns.interactivestory D/ HostConnection::get() New Host Connection established 0xa6659ac0, tid 2293
05-06 20:58:27.556    2276-2293/dredaydesigns.interactivestory I/OpenGLRenderer Initialized EGL, version 1.4
05-06 20:58:27.899    2276-2293/dredaydesigns.interactivestory D/OpenGLRenderer Enabling debug mode 0
05-06 20:58:27.933    2276-2293/dredaydesigns.interactivestory W/EGL_emulation eglSurfaceAttrib not implemented
05-06 20:58:27.933    2276-2293/dredaydesigns.interactivestory W/OpenGLRenderer Failed to set EGL_SWAP_BEHAVIOR on surface 0xa66c0080, error=EGL_SUCCESS
05-06 20:58:28.044    2276-2276/dredaydesigns.interactivestory I/Choreographer Skipped 34 frames!  The application may be doing too much work on its main thread.
05-06 20:58:50.728    2276-2276/dredaydesigns.interactivestory D/StoryActivity dre
05-06 20:58:50.754    2276-2276/dredaydesigns.interactivestory D/AndroidRuntime Shutting down VM
    --------- beginning of crash
05-06 20:58:50.755    2276-2276/dredaydesigns.interactivestory E/AndroidRuntime FATAL EXCEPTION: main
    Process: dredaydesigns.interactivestory, PID: 2276
    java.lang.RuntimeException: Unable to start activity ComponentInfo{dredaydesigns.interactivestory/dredaydesigns.interactivestory.ui.StoryActivity}: java.lang.NullPointerException: Attempt to invoke virtual method 'void android.widget.ImageView.setImageDrawable(android.graphics.drawable.Drawable)' on a null object reference
            at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2298)
            at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2360)
            at android.app.ActivityThread.access$800(ActivityThread.java:144)
            at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1278)
            at android.os.Handler.dispatchMessage(Handler.java:102)
            at android.os.Looper.loop(Looper.java:135)
            at android.app.ActivityThread.main(ActivityThread.java:5221)
            at java.lang.reflect.Method.invoke(Native Method)
            at java.lang.reflect.Method.invoke(Method.java:372)
            at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:899)
            at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:694)
     Caused by: java.lang.NullPointerException: Attempt to invoke virtual method 'void android.widget.ImageView.setImageDrawable(android.graphics.drawable.Drawable)' on a null object reference
            at dredaydesigns.interactivestory.ui.StoryActivity.loadPage(StoryActivity.java:53)
            at dredaydesigns.interactivestory.ui.StoryActivity.onCreate(StoryActivity.java:44)
            at android.app.Activity.performCreate(Activity.java:5937)
            at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1105)
            at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2251)
            at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2360)
            at android.app.ActivityThread.access$800(ActivityThread.java:144)
            at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1278)
            at android.os.Handler.dispatchMessage(Handler.java:102)
            at android.os.Looper.loop(Looper.java:135)
            at android.app.ActivityThread.main(ActivityThread.java:5221)
            at java.lang.reflect.Method.invoke(Native Method)
            at java.lang.reflect.Method.invoke(Method.java:372)
            at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:899)
            at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:694)
05-06 20:58:50.895    2276-2289/dredaydesigns.interactivestory I/art Background sticky concurrent mark sweep GC freed 2932(136KB) AllocSpace objects, 0(0B) LOS objects, 0% free, 3MB/3MB, paused 1.138ms total 115.674ms
05-06 20:59:01.850    2276-2276/dredaydesigns.interactivestory I/Process Sending signal. PID: 2276 SIG: 9

i went and looked at the code at line 53 in story activity but there are no red markers or anything? here is my code

package dredaydesigns.interactivestory.ui;

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

import dredaydesigns.interactivestory.R;
import dredaydesigns.interactivestory.model.Page;
import dredaydesigns.interactivestory.model.Story;


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

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_story);
        Intent intent = getIntent();
        String name = intent.getStringExtra(getString(R.string.key_name));
        if (name == null) {
            name = "Friend";
        }

        Log.d(TAG,name);

        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 = getResources().getDrawable(mCurrentPage.getImageId());
                mImageView.setImageDrawable(drawable);

        mTextView.setText(mCurrentPage.getText());
        if (mCurrentPage.isFinal()){

            mChoice1.setVisibility(View.INVISIBLE);
            mChoice2.setText("PLAY AGAIN!");
            mChoice2.setOnClickListener(new View.OnClickListener(){
                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);
            }
        });

    }

}}

Hello,

There are a lot of places the issue could be located, but I cannot know for sure without more code? Would you be able to put your code on github? If not, could you at least post here your activity_story.xml, Story.java, and Page.java files?

Andreas Robichaux
Andreas Robichaux
2,426 Points

activity_story.xml

activity_story.xml
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context="dredaydesigns.interactivestory.ui.StoryActivity"
    android:background="@android:color/white">

    <ImageView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:id="@+id/StoryImageView"
        android:layout_alignParentLeft="true"
        android:layout_alignParentStart="true"
        android:layout_alignParentTop="true"
        android:layout_alignParentRight="true"
        android:layout_alignParentEnd="true"
        android:src="@drawable/page0"
        android:scaleType="fitXY"
        android:adjustViewBounds="true" />

    <TextView
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:id="@+id/storyTextView"
        android:layout_below="@+id/StoryImageView"
        android:layout_alignLeft="@+id/StoryImageView"
        android:layout_alignStart="@+id/StoryImageView"
        android:text="&quot;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.&quot;"
        android:paddingTop="15dp"
        android:paddingLeft="30dp"
        android:paddingRight="30dp"
        android:lineSpacingMultiplier="1.4"/>

    <Button
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="Stop and Investigate!"
        android:id="@+id/choiceButton2"
        android:background="@android:color/white"
        android:textColor="#ff3a8aec"
        android:layout_alignParentBottom="true"
        android:layout_alignLeft="@+id/storyTextView"
         />

    <Button
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="Continue Home to Earth"
        android:id="@+id/choiceButton1"
        android:background="@android:color/white"
        android:textColor="#ff3a8aec"
        android:layout_above="@+id/choiceButton2"
        android:layout_alignLeft="@+id/choiceButton2"
        android:layout_alignStart="@+id/choiceButton2" />
</RelativeLayout>
story.java
package dredaydesigns.interactivestory.model;

import dredaydesigns.interactivestory.R;

/**
 * Created by Andreas on 5/4/2015.
 */
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];

    }

    }
page.java
package dredaydesigns.interactivestory.model;

/**
 * Created by Andreas on 5/4/2015.
 */
public class Page {
    private int mImageId;
    private String mText;
    private Choice mChoice1;
    private Choice mChoice2;
    private boolean mIsFinal;

    public Page(int imageId, String text, Choice choice1, Choice choice2){
        mImageId = imageId;
        mText = text;
        mChoice1 = choice1;
        mChoice2 = choice2;
    }

    public boolean isFinal() {
        return mIsFinal;
    }

    public void setFinal(boolean isFinal) {
        mIsFinal = isFinal;
    }

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

    }
    public int getImageId() {
        return mImageId;
    }


    public String getText() {
        return mText;
    }

    public void setText(String text) {
        mText = text;
    }
    public Choice getChoice1() {
        return mChoice1;
    }

    public void setChoice1(Choice choice1) {
        mChoice1 = choice1;
    }

    public Choice getChoice2() {
        return mChoice2;
    }

    public void setChoice2(Choice choice2) {
        mChoice2 = choice2;
    }

    public void setImageId(int id){
        mImageId = id;
    }

}
Andreas Robichaux
Andreas Robichaux
2,426 Points
activity_story.xml
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context="dredaydesigns.interactivestory.ui.StoryActivity"
    android:background="@android:color/white">

    <ImageView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:id="@+id/StoryImageView"
        android:layout_alignParentLeft="true"
        android:layout_alignParentStart="true"
        android:layout_alignParentTop="true"
        android:layout_alignParentRight="true"
        android:layout_alignParentEnd="true"
        android:src="@drawable/page0"
        android:scaleType="fitXY"
        android:adjustViewBounds="true" />

    <TextView
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:id="@+id/storyTextView"
        android:layout_below="@+id/StoryImageView"
        android:layout_alignLeft="@+id/StoryImageView"
        android:layout_alignStart="@+id/StoryImageView"
        android:text="&quot;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.&quot;"
        android:paddingTop="15dp"
        android:paddingLeft="30dp"
        android:paddingRight="30dp"
        android:lineSpacingMultiplier="1.4"/>

    <Button
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="Stop and Investigate!"
        android:id="@+id/choiceButton2"
        android:background="@android:color/white"
        android:textColor="#ff3a8aec"
        android:layout_alignParentBottom="true"
        android:layout_alignLeft="@+id/storyTextView"
         />

    <Button
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="Continue Home to Earth"
        android:id="@+id/choiceButton1"
        android:background="@android:color/white"
        android:textColor="#ff3a8aec"
        android:layout_above="@+id/choiceButton2"
        android:layout_alignLeft="@+id/choiceButton2"
        android:layout_alignStart="@+id/choiceButton2" />
</RelativeLayout>
story.java
package dredaydesigns.interactivestory.model;

import dredaydesigns.interactivestory.R;

/**
 * Created by Andreas on 5/4/2015.
 */
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];

    }

    }
page.java
package dredaydesigns.interactivestory.model;

/**
 * Created by Andreas on 5/4/2015.
 */
public class Page {
    private int mImageId;
    private String mText;
    private Choice mChoice1;
    private Choice mChoice2;
    private boolean mIsFinal;

    public Page(int imageId, String text, Choice choice1, Choice choice2){
        mImageId = imageId;
        mText = text;
        mChoice1 = choice1;
        mChoice2 = choice2;
    }

    public boolean isFinal() {
        return mIsFinal;
    }

    public void setFinal(boolean isFinal) {
        mIsFinal = isFinal;
    }

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

    }
    public int getImageId() {
        return mImageId;
    }


    public String getText() {
        return mText;
    }

    public void setText(String text) {
        mText = text;
    }
    public Choice getChoice1() {
        return mChoice1;
    }

    public void setChoice1(Choice choice1) {
        mChoice1 = choice1;
    }

    public Choice getChoice2() {
        return mChoice2;
    }

    public void setChoice2(Choice choice2) {
        mChoice2 = choice2;
    }

    public void setImageId(int id){
        mImageId = id;
    }

}

3 Answers

Harry James
Harry James
14,780 Points

Hey Andreas!

Your problem lies here:

mImageView.setImageDrawable(drawable);

(Line 53 of StoryActivity)

The error is located here in the log:

Caused by: java.lang.NullPointerException: Attempt to invoke virtual method 'void android.widget.ImageView.setImageDrawable(android.graphics.drawable.Drawable)' on a null object reference
            at dredaydesigns.interactivestory.ui.StoryActivity.loadPage(StoryActivity.java:53)

So, what is happening is we're attempting to call setImageDrawable() on null! This means that you mustn't have set mImageView or, it isn't set correctly.

I can see that you have set mImageView to an ImageView however, so I wonder if it's because this ImageView doesn't actually exist. Can you check your activity_story.xml file to see if you have in fact named your imageView storyImageView, following the same case.


Hope it helps but, if you're still getting an error and don't know why, provide your activity_story.xml file here and I'll take a look. Also, make sure you're not calling loadPage() before you set the variable.

EDIT: As I was typing this, you updated the post with a new comment - I'll take a look at this now


EDIT2:

Thanks for providing the file. I've noticed that you've got mismatching cases. Your ImageView in the XML shows this:

android:id="@+id/StoryImageView"

(Capital S)

But your Java file shows this:

mImageView = (ImageView)findViewById(R.id.storyImageView);

(Lowercase s)

Be sure to only pick one case - it needs to be the same in both places.


Hope it helps and, if you have any more questions/problems, give me a shout :)

Hello,

In your StoryActivity.java file, you are referencing the ImageView with the id of storyImageView, when in your xml, you have it as StoryImageView. I'd recommend changing the xml id to be storyImageView. Also, your other ids in the xml are the same way so I'd recommend changing those as well