0

I'm writing a basic word scramble app in Android Studio, and have gotten everything laid out and the methods working, but I'm getting a fatal exception when I send it to my debugger.

Here's my java:

package com.example.admin.androidwordscramble;
import android.support.v7.app.ActionBarActivity;
import android.os.Bundle;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.widget.TextView;
import java.util.Random;
import java.util.Scanner;


public class WordScramble extends ActionBarActivity {
EditText playerEdit;
TextView textUpper;
TextView textInstruction;
Button buttonNew;
Button buttonPlay;
String playerInput;
char[] answerWord;
char[] playerWord;
char[] scrambledWord;
final String word1 = "APPLE";
final String word2 = "CLOVE";
final String word3 = "LEMON";
final String word4 = "ONION";

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_word_scramble);
    initControls();    //Where my logcat says the first error is.
}


@Override
public boolean onCreateOptionsMenu(Menu menu) {
    // Inflate the menu; this adds items to the action bar if it is present.
    getMenuInflater().inflate(R.menu.menu_word_scramble, 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();

    //noinspection SimplifiableIfStatement
    if (id == R.id.action_settings) {
        return true;
    }
    return super.onOptionsItemSelected(item);
}

void initControls() {
    playerEdit = (EditText)findViewById(R.id.playerEdit);
    textUpper = (TextView)findViewById(R.id.textUpper);
    textInstruction = (TextView)findViewById((R.id.textInstruction));
    textUpper.setText("Scramble Game");

    buttonNew.setOnClickListener(new Button.OnClickListener()    //Where the logcat says the second error is.
    {
        public void onClick
                (View v) { newGame();}});
    buttonPlay.setOnClickListener(new Button.OnClickListener()
    {public void onClick
                (View v) { playGame();}});
}

void newGame() {
    playerEdit.setText("");
    answerWord = toArray(word1);
    shuffle(answerWord);
    textUpper.setText(scrambledWord.toString());
    textInstruction.setText("Unscramble it!");
}

void playGame() {
    playerInput = playerEdit.getText().toString();
    playerWord = toArray(playerInput);

    if(testWord()) {
        textUpper.setText(answerWord.toString());
        textInstruction.setText("Correct!");
    }
    else {
        textInstruction.setText("Incorrect. Try again!");
    }
}

char[] shuffle(char[] answerWord) {
    Random rand = new Random();
    char[] scrambledWord = new char[5];

    for (int i = 0; i < scrambledWord.length; i++)
        scrambledWord[i] = answerWord[i];

    final int max = 5;
    for (int i = 0; i < max; i++) {
        int k = rand.nextInt(scrambledWord.length);
        int j = rand.nextInt(scrambledWord.length);
        char temp = scrambledWord[k];
        scrambledWord[k] = scrambledWord[j];
        scrambledWord[j] = temp;
    }
    return scrambledWord;
}

boolean testWord() {
    final int max = 5;
    int i = 0;
    while (i < max) {
        if (playerWord[i] != answerWord[i])
            return false;
        else {
            i++;
        }
    }
    return true;
}

    char[] toArray(String wordString) {
    Scanner read = new Scanner(wordString);
    char[] wordArray = new char[5];

    for (int i = 0; i < 5; i++) {
        wordArray[i] = wordString.charAt(i);
    }
    return wordArray;
}
}

My 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" android:paddingLeft="@dimen/activity_horizontal_margin"
android:paddingRight="@dimen/activity_horizontal_margin"
android:paddingTop="@dimen/activity_vertical_margin"
android:paddingBottom="@dimen/activity_vertical_margin" tools:context=".WordScramble">

<Button
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:text="NEW"
    android:id="@+id/buttonNew"
    android:layout_marginBottom="58dp"
    android:layout_alignParentBottom="true"
    android:layout_alignParentLeft="true"
    android:layout_alignParentStart="true"
    android:layout_marginLeft="47dp"
    android:layout_marginStart="47dp" />

<Button
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:text="PLAY"
    android:id="@+id/buttonPlay"
    android:layout_alignTop="@+id/buttonNew"
    android:layout_alignParentRight="true"
    android:layout_alignParentEnd="true"
    android:layout_marginRight="47dp"
    android:layout_marginEnd="47dp" />

<TextView
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:textAppearance="?android:attr/textAppearanceLarge"
    android:text="Unscramble it!"
    android:id="@+id/textInstruction"
    android:layout_above="@+id/buttonNew"
    android:layout_centerHorizontal="true"
    android:layout_marginBottom="167dp" />

<EditText
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:id="@+id/playerEdit"
    android:layout_above="@+id/buttonNew"
    android:layout_centerHorizontal="true"
    android:layout_marginBottom="75dp"
    android:inputType="text"
    android:hint="Try here"
    android:textIsSelectable="true"
    android:capitalize="characters" />

<TextView
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:text="New Text"
    android:id="@+id/textUpper"
    android:layout_above="@+id/textInstruction"
    android:layout_centerHorizontal="true"
    android:layout_marginBottom="36dp" />

Log cat states:

E/AndroidRuntime﹕ FATAL EXCEPTION: main
    Process: com.example.admin.androidwordscramble, PID: 2405
    java.lang.RuntimeException: Unable to start activity ComponentInfo{com.example.admin.androidwordscramble/com.example.admin.androidwordscramble.WordScramble}: java.lang.NullPointerException: Attempt to invoke virtual method 'void android.widget.Button.setOnClickListener(android.view.View$OnClickListener)' on a null object reference
            ....
Caused by: java.lang.NullPointerException: Attempt to invoke virtual method 'void android.widget.Button.setOnClickListener(android.view.View$OnClickListener)' on a null object reference
            at com.example.admin.androidwordscramble.WordScramble.initControls(WordScramble.java:67)
            at com.example.admin.androidwordscramble.WordScramble.onCreate(WordScramble.java:36)

I've cleaned and rebuilt a couple times, but it still crashes the emulator and spits out an exception in the debugger. Can anyone point out where I went wrong with the button pointing?

Edit: Logcat for when the app froze:

    07-29 14:39:00.168      627-653/? E/ActivityManager﹕ ANR in com.example.admin.project03 (com.example.admin.project03/.WordScramble)
    PID: 1782
    Reason: Input dispatching timed out (Waiting to send non-key event because the touched window has not finished processing certain input events that were delivered to it over 500.0ms ago.  Wait queue length: 2.  Wait queue head age: 13282.2ms.)
    Load: 0.95 / 0.57 / 0.23
    CPU usage from 7918ms to 0ms ago:
    99% 1782/com.example.admin.project03: 99% user + 0% kernel / faults: 3756 minor
    2.6% 627/system_server: 0.1% user + 2.5% kernel / faults: 77 minor
    1.2% 250/vinput: 0% user + 1.2% kernel
    0.1% 8/rcu_preempt: 0% user + 0.1% kernel
    0% 96/adbd: 0% user + 0% kernel / faults: 2 minor
    0% 245/healthd: 0% user + 0% kernel
    0.1% 254/local_gps: 0% user + 0.1% kernel
    0% 783/wpa_supplicant: 0% user + 0% kernel
    25% TOTAL: 24% user + 0.6% kernel + 0.3% softirq
    CPU usage from 2350ms to 2858ms later:
    101% 1782/com.example.admin.project03: 101% user + 0% kernel / faults: 200 minor
    98% 1782/admin.project03: 98% user + 0% kernel
    1.8% 1797/GCDaemon: 1.8% user + 0% kernel
    5.8% 627/system_server: 1.9% user + 3.9% kernel / faults: 3 minor
    1.9% 639/FinalizerDaemon: 0% user + 1.9% kernel
    1.9% 645/SensorService: 0% user + 1.9% kernel
    1.9% 653/ActivityManager: 1.9% user + 0% kernel
    26% TOTAL: 25% user + 1% kernel
07-29 14:39:00.338     627-1830/? D/OpenGLRenderer﹕ Render dirty regions requested: true
07-29 14:39:00.338      627-653/? D/Atlas﹕ Validating map...
07-29 14:39:00.437     627-1830/? I/OpenGLRenderer﹕ Initialized EGL, version 1.4
07-29 14:39:00.437     627-1830/? D/﹕ HostConnection::get() New Host Connection established 0xafc9b9a0, tid 1830
07-29 14:39:00.532      627-645/? D/Sensors﹕ Client connection accepted (186)
07-29 14:39:00.632     627-1830/? D/OpenGLRenderer﹕ Enabling debug mode 0
07-29 14:39:00.644     627-1830/? W/EGL_emulation﹕ eglSurfaceAttrib not implemented
07-29 14:39:00.644     627-1830/? W/OpenGLRenderer﹕ Failed to set EGL_SWAP_BEHAVIOR on surface 0xafca9480, error=EGL_SUCCESS

Edit2: Added a while statement to prevent a crash if playGame was called, but now getting a FATAL NullpointerException right at the while statement.

void playGame() {
    while (answerWord != null) {
        playerInput = playerEdit.getText().toString();
        playerWord = toArray(playerInput);

        if (testWord()) {
            textUpper.setText(answerWord.toString());
            textInstruction.setText("Correct!");
        } else {
            textInstruction.setText("Incorrect. Try again!");
        }
    }
}
Clay
  • 4,700
  • 3
  • 33
  • 49
fluffywarthog
  • 61
  • 1
  • 2
  • 12

1 Answers1

1

Your buttonNew and buttonPlay are never initialized before calling the setOnClickListener, you need to add findViewById statements, to get a handle to the buttons in the view, giving them the same id in XML as the variable name does not give you the handle. So, before setting the OnClickListener you need to add ::

buttonNew = (Button) findViewById(R.id.buttonNew);
buttonPlay = (Button) findViewById(R.id.buttonPlay);

Just like you did for playerEdit, etc. All the variables are initialized null by default, so without finding the view, you are calling setOnClickListener on null object, and hence the exception.

user007
  • 2,156
  • 2
  • 20
  • 35
  • Thanks, that took care of the button problem. Now I've got a NoSuchElementException in my toArray() method, when I assign wordArray[i] to the character I've read from the string. I've initialized the array and the string I've passed is 'final', so I'm a bit confused as to why I'm getting this exception. – fluffywarthog Jul 29 '15 at 15:42
  • Okay, fixed the NoSuchElement by adding a while(hasNext()) condition, but now the entire app hangs when I use the newGame() button. Logcat says: "Skipped 32 frames! The application may be doing too much work on its main thread." I don't think this app should be using that much resources. – fluffywarthog Jul 29 '15 at 16:01
  • 1
    @fluffywarthog is there any other exception in the logcat after that?? Because I found this http://stackoverflow.com/questions/23001873/skipped-32-frames-the-application-may-be-doing-too-much-work-on-its-main-thread and it actually turned out to be a NULL pointer exception at the end. – user007 Jul 29 '15 at 16:05
  • @fluffywarthog : http://stackoverflow.com/a/21126690/4106624 Take a look at this as well. This might help – user007 Jul 29 '15 at 16:08
  • posted my logcat from the most common error, and getting a new NullPointerException when I added a while statement to playGame(). – fluffywarthog Jul 29 '15 at 19:36
  • 1
    @fluffywarthog : why do you create a `Scanner read` in `toArray` function?? And how do you exit the while loop of `playGame` you don't seem to modify `answerWord` in the while loop! – user007 Jul 29 '15 at 20:29
  • Thank you. Changed the while() loop in `playGame` to an if(). The `Scanner read` was from an earlier attempt where I was using `while(hasNext())` conditional and `next()` to read chars. – fluffywarthog Jul 30 '15 at 14:33