Buttons aren't responding: Java in Android Studio

Agent67

Honorary Master
Joined
Nov 7, 2020
Messages
28,008
Reaction score
20,150
Location
Western Cape
So for my final assignment of the year, we have to make a Bingo App with three screens. I've made good progress so far, but for some reason all of a sudden, the buttons on my second screen aren't working at all. Even tho I don't see anything wrong with their on-click methods at a quick glance. The other screens' buttons work, but it's just this one's buttons that aren't firing. I'm not sure how I can fix this...

The code:
Java:
// The screen in question
public class DisplayActivity extends AppCompatActivity {
    private static final String BINGO_HISTORY_FILE = "bingohistory.txt";

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

        // Get the contents of the array from the MainActivity and display them
        TextView txtCurrent = (TextView) findViewById(R.id.txtCurrent);
        int[] NumbersCalled = MainActivity.NumbersCalled;
        final String outputString = getOutputString(NumbersCalled);
        txtCurrent.setText("Numbers called: " + outputString);


        // Event handler for the Go Back to Main Menu button
        Button returnBtn = (Button) findViewById(R.id.btnReturn);
        returnBtn.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                MainActivity.NumbersCalled = NumbersCalled;
                DisplayActivity.this.finish();
                startActivity(new Intent(DisplayActivity.this, MainActivity.class));
            }
        });

        // Event handler for the Save button
        Button saveBtn = (Button) findViewById(R.id.btnReturn);
        saveBtn.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                // Save the current bingo numbers after the game is finished
                writeToFile(outputString);
            }
        });
    }

    private String getOutputString(int[] NumbersCalled) {
        String temp = "";
        for (int i = 0; i < NumbersCalled.length; i++) {
            temp += NumbersCalled[i] + " ";
        }
        final String outputString = temp;
        return outputString;
    }

    protected void writeToFile(String data) {
        // Write the current numbers to the "bingohistory.txt" text file.
        // Check for exceptions when attempting to write to the file
        FileOutputStream file = null;
        try {
            file = openFileOutput(BINGO_HISTORY_FILE,
                    DisplayActivity.this.MODE_PRIVATE);
        } catch (IOException e) {
            e.printStackTrace();
            Toast.makeText(DisplayActivity.this,
                    "Couldn't find file", Toast.LENGTH_LONG).show();
        }
        OutputStreamWriter osw = new OutputStreamWriter(file);
        BufferedWriter bw = new BufferedWriter(osw);
        try {
            bw.write(data);
        } catch (IOException e) {
            e.printStackTrace();
            Toast.makeText(DisplayActivity.this,
                    "Couldn't write to file", Toast.LENGTH_LONG).show();
        }
        try {
            bw.newLine();
        } catch (IOException e) {
            e.printStackTrace();
            Toast.makeText(DisplayActivity.this,
                    "Couldn't write to file", Toast.LENGTH_LONG).show();
        }
        try {
            bw.close();
        } catch (IOException e) {
            e.printStackTrace();
            Toast.makeText(DisplayActivity.this,
                    "Couldn't write to file", Toast.LENGTH_LONG).show();
        }
        try {
            osw.close();
        } catch (IOException e) {
            e.printStackTrace();
            Toast.makeText(DisplayActivity.this,
                    "Couldn't write to file", Toast.LENGTH_LONG).show();
        }
    }
}

// The Main Menu's screen
public class MainActivity extends AppCompatActivity {
    // Declare class-level variables
    public static int currentNumber;
    public static int[] NumbersCalled = {currentNumber};

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

        // Get the first number to be displayed. Save the number to be displayed
        // in the NumbersCalled array and display the number in the textview
        TextView txtCurrentNumber = (TextView) findViewById(R.id.txtNumber);
        getAndSaveNewNumber();
        txtCurrentNumber.setText(String.valueOf(currentNumber));

        // Event handler for the Exit button
        Button exitAppBtn = (Button) findViewById(R.id.btnExit);
        exitAppBtn.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                // Finish and exit the app
                MainActivity.this.finish();
                System.exit(0);
            }
        });

        // Event handler for the Next button
        Button nextBtn = (Button) findViewById(R.id.btnNext);
        nextBtn.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                // Get the next number to be displayed. Save the number to be displayed
                // in the NumbersCalled array and display the number in the textview
                getAndSaveNewNumber();
                txtCurrentNumber.setText(String.valueOf(currentNumber));
            }
        });

        // Event handler for the Bingo button
        Button bingoBtn = (Button) findViewById(R.id.btnBingo);
        bingoBtn.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                startActivity(new Intent(MainActivity.this, DisplayActivity.class).putExtra("NumbersCalled", NumbersCalled));
            }
        });

        // Event handler for the Display button
        Button displayBtn = (Button) findViewById(R.id.btnDisplay);
        displayBtn.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                startActivity(new Intent(MainActivity.this, DisplayActivity.class).putExtra("NumbersCalled", NumbersCalled));
            }
        });

        // Event handler for the History button
        Button historyBtn = (Button) findViewById(R.id.btnHistory);
        historyBtn.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                startActivity(new Intent(MainActivity.this, HistoryActivity.class));
            }
        });
    }

    // Generate a new random number and save it to the NumbersCalled array
    // Then proceed to sort the array in ascending order
    public void getAndSaveNewNumber() {
        currentNumber = (int)Math.floor(Math.random() * (99 - 0 + 1) + 0);

        //Check if number has been called before, if so, don't add to the array nor display it.
        if (checkNumbersCalled(currentNumber)) {
            currentNumber = (int)Math.floor(Math.random() * (99 - currentNumber + 1) + 0);
            saveNewNumber();
        } else {
            saveNewNumber();
        }

        // Sort the array in asc order
        Arrays.sort(NumbersCalled);
    }

    // Go through the NumbersChecked array and check if n is already in the array
    public boolean checkNumbersCalled(int n) {
        for (int i = 0; i < NumbersCalled.length; i++) {
            if (NumbersCalled[i] == currentNumber) {
                return true;
            }
        }
        return false;
    }

    // Add a number to the array
    public void saveNewNumber() {
        // Add number to the array
            // Create a new array with the current number
            // then substitute the NumbersCalled array's value with the new array
            int n = NumbersCalled.length;
            int[] NewArray = new int[n + 1];
            for (int i = 0; i < n; i++) {
                NewArray[i] = NumbersCalled[i];
            }
            NewArray[n] = currentNumber;
            NumbersCalled = NewArray;
    }
}

}
 
Java:
        Button returnBtn = (Button) findViewById(R.id.btnReturn);
        returnBtn.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                MainActivity.NumbersCalled = NumbersCalled;
                DisplayActivity.this.finish();
                startActivity(new Intent(DisplayActivity.this, MainActivity.class));
            }
        });

        // Event handler for the Save button
        Button saveBtn = (Button) findViewById(R.id.btnReturn);
        saveBtn.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                // Save the current bingo numbers after the game is finished
                writeToFile(outputString);
            }
        });
    }
}

}

Just using these as an example:

So, I assume you've done the following:

1. Checked the id is valid for the button? and in the resource - though these are generated, its still worth while double checking.
2. Added a breakpoint inside the onClick event(s) to see if the program does indeed execute these lines?
Been awhile since I did Android dev (iOS dev full time) - but why aren't you using Kotlin? Or is that due to the course being s Java course and not a mobile app source?
 
Just using these as an example:
Ayyyyyy, Honourable Member, long time no chat.
So, I assume you've done the following:

1. Checked the id is valid for the button? and in the resource - though these are generated, its still worth while double checking.
I mean I did use the drag-and-drop UI to create my GUIs... I didn't code them directly.
2. Added a breakpoint inside the onClick event(s) to see if the program does indeed execute these lines?]
Haven't done that as of yet. But I do click the buttons like crazy when it runs. So I'm not sure why it wouldn't run the listeners at least?
Been awhile since I did Android dev (iOS dev full time) - but why aren't you using Kotlin? Or is that due to the course being s Java course and not a mobile app source?
The module is Java-based. At least I now know that I don't like Java just like I don't like C++...
 
Ayyyyyy, Honourable Member, long time no chat.

I mean I did use the drag-and-drop UI to create my GUIs... I didn't code them directly.

Haven't done that as of yet. But I do click the buttons like crazy when it runs. So I'm not sure why it wouldn't run the listeners at least?

The module is Java-based. At least I now know that I don't like Java just like I don't like C++...

Java isn't terrible; but Swift and Kotlin is better lol

I suggest posting this question to StackOverFlow rather mind you. They'll be able to direct you better. A quick glance at the code, suggests it _should_ work.
 
Last edited:
@Priapus I got it. I accidentally linked both returnBtn and saveBtn to the same button (R.id.btnReturn), thus creating two onclicklisteners for the same button. They must've clashed somehow. The buttons are finally working now...

Btw where can I look in the files for where a generated text file can be saved?
 
@Priapus I got it. I accidentally linked both returnBtn and saveBtn to the same button (R.id.btnReturn), thus creating two onclicklisteners for the same button. They must've clashed somehow. The buttons are finally working now...

Btw where can I look in the files for where a generated text file can be saved?


Oops, I missed that - sorry. Yeah that would cause it.

The resources locates inside res directory of your app. The Android resource compiler processes resources arcording to which subforder they are in and the format of the file, for example:

  • res/drawable: Contains all resources file that can be drawable, such as (.png, .jpg, .gif) or xml file.
  • res/layout: Contains all resources file that defines user interface layout, such as activity_main.xml, fragment_login.xml.
  • res/color: Contains all resources file that defines list of colors that used in your app.
  • res/value: Contains all resources file that contains simple value like string, integer, etc.
  • ...

See App resources overview and Resourcce types overview
 
@Priapus I got it. I accidentally linked both returnBtn and saveBtn to the same button (R.id.btnReturn), thus creating two onclicklisteners for the same button. They must've clashed somehow. The buttons are finally working now...

Btw where can I look in the files for where a generated text file can be saved?
I have to say with Android studio "And yes I know it is not the same thing" it makes it very easy to figure this stuff out. Just saying it is not as piss poor as people make it out to be. It is actually really nice.
 
Look, I know I will get a lot of hate but I ran your code trough ChatGPT and it said the following.

The code seems mostly correct, but there is one issue in the DisplayActivity class in the onCreate method. The mistake is in assigning the same click listener for both the "Return" button and the "Save" button. Both buttons have the same ID, R.id.btnReturn, so they both reference the same button. You should assign the click listener for the "Save" button separately.

It is a really good tool don't be afraid to use it. I use it all the time and it really is a powerful tool. I know you already found the problem but I just wanted to show you how fast it can actually find little mistakes.
 
Look, I know I will get a lot of hate but I ran your code trough ChatGPT and it said the following.



It is a really good tool don't be afraid to use it. I use it all the time and it really is a powerful tool. I know you already found the problem but I just wanted to show you how fast it can actually find little mistakes.

Yup, sometimes ChatGPT is pretty good
 
I have to say with Android studio "And yes I know it is not the same thing" it makes it very easy to figure this stuff out. Just saying it is not as piss poor as people make it out to be. It is actually really nice.

It's a lot better than it used to be. However, the IDE would never catch this mistake - as syntactically, it's correct and there is no "context" for the code the IDE can infer.
 
It's a lot better than it used to be. However, the IDE would never catch this mistake - as syntactically, it's correct and there is no "context" for the code the IDE can infer.
This sounds stupid, but what I do with my buttons is comment them both on the HTML side and Java side. That way, I know where everything is. I humbly and truly don't know if it is best practice or not, but it works really well for me, especially if I am adding a lot of functions. Again, I am not a professional, but I figured comments are there for a reason, so I make little notes as far as I go. After I link the buttons I normally comment in "used" My code is very messy but no one really sees it and it is for my personal use so I think it is ok?
 
This sounds stupid, but what I do with my buttons is comment them both on the HTML side and Java side. That way, I know where everything is. I humbly and truly don't know if it is best practice or not, but it works really well for me, especially if I am adding a lot of functions. Again, I am not a professional, but I figured comments are there for a reason, so I make little notes as far as I go. After I link the buttons I normally comment in "used" My code is very messy but no one really sees it and it is for my personal use so I think it is ok?

Yes, then do whatever works for you. One thing to keep in mind though; write your code in a way that if you returned to the project six months from now, you still understand what is going on.
 
Yes, then do whatever works for you. One thing to keep in mind though; write your code in a way that if you returned to the project six months from now, you still understand what is going on.
Ain't that the truth...
 
Yes, then do whatever works for you. One thing to keep in mind though; write your code in a way that if you returned to the project six months from now, you still understand what is going on.
What I do is I write little comment as notes that are very detailed. Essentially explaining to myself what the function is where it will be used and what its purpose is. The nice part is I can borrow from my own code. I can copy and paste sections and with very litte tinkering get them to work properly. Comments have saved my sanity so many times.

But to get back to ChatGPT, every coder should use it. It really does help with trouble shooting 70% of the time for me personally. When I am more established I will sub to the pro version. But for now it speeds up my work ten fold. The obvious dengour is spoon feeding so I still try to use it as little as possible. I even add in my notes where ChatGPT helped me because sometimes it also gets it wrong now and then and it is a good place to start looking.
 
What I do is I write little comment as notes that are very detailed. Essentially explaining to myself what the function is where it will be used and what its purpose is. The nice part is I can borrow from my own code. I can copy and paste sections and with very litte tinkering get them to work properly. Comments have saved my sanity so many times.

Whilst this works for you; do try write your code in a more expressive way. The old saying goes, that code should be self documenting - comments should explain the WHY and not the WHAT.

But to get back to ChatGPT, every coder should use it. It really does help with trouble shooting 70% of the time for me personally. When I am more established I will sub to the pro version. But for now it speeds up my work ten fold. The obvious dengour is spoon feeding so I still try to use it as little as possible. I even add in my notes where ChatGPT helped me because sometimes it also gets it wrong now and then and it is a good place to start looking.

I've never used ChatGPT for coding and never will. Perhaps when I was just starting out, it would have helped. But as you hinted, that could have also slowed my progress down. I like to figure out issues on my own to have a better understanding of the system(s) I work with. If I get really stuck, I will reach to StackOverFlow and search for answers there - but that's not common these days.

Then again, I have been coding for 10 years and experienced enough to know how to find the answers to issues I have. You'll get there too with experience and time.
 
Top
Sign up to the MyBroadband newsletter
X