Force closes caused by onClickListener - java

I made just one activity that opens another activity. Everything was working right until i setted up onClickListener. Now my app force closes when it launch. Without these two lines application launches correctly:
BUeasycounter.setOnClickListener(this);
BUrps.setOnClickListener(this);
Here is my full source:
package com.dano.learning;
import android.app.Activity;
import android.content.Intent;
import android.os.Bundle;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
public class Menu extends Activity implements View.OnClickListener{
Button BUeasycounter;
Button BUrps;
#Override
protected void onCreate(Bundle MyBundle) {
super.onCreate(MyBundle);
setContentView(R.layout.activity_main);
initializeVars();
// next 2 lines cause the problem
BUeasycounter.setOnClickListener(this);
BUrps.setOnClickListener(this);
}
public void initializeVars(){
Button BUeasycounter= (Button) findViewById(R.id.BUeasycounter);
Button BUrps = (Button) findViewById(R.id.BUrps);
}
public void onClick(View v) {
switch (v.getId()){
case R.id.BUeasycounter:
Intent openEasyCounter = new Intent("com.dano.learning.EASYCOUNTER");
startActivity(openEasyCounter);
break;
case R.id.BUrps:
Intent openRPS = new Intent("com.dano.learning.EASYCOUNTER");
startActivity(openRPS);
break;
};
}
}
Maybe i just typed something wrong but I cant find mistake in my source for more than two days. Thank you for your help.

There is no exception stack in question, but based on code I see one issue is:
Button BUeasycounter;
Button BUrps;
Both are pointing to null which could be throwing NullPointerException when you do
BUeasycounter.setOnClickListener(this);
BUrps.setOnClickListener(this);
Remove new variable in initializeVars method.
Example:
public void initializeVars(){
BUeasycounter= (Button) findViewById(R.id.BUeasycounter);
BUrps = (Button) findViewById(R.id.BUrps);
}
Note: Java naming convention suggest that use small letter as first letter for variable name.

remove smi-colon after swich case :
public void onClick(View v) {
// TODO Auto-generated method stub
switch (v.getId()){
case R.id.BUeasycounter:
Intent openEasyCounter = new Intent("com.dano.learning.EASYCOUNTER");
startActivity(openEasyCounter);
break;
case R.id.BUrps:
Intent openRPS = new Intent("com.dano.learning.EASYCOUNTER");
startActivity(openRPS);
break;
} //>>>> from here remove semi-colon
and change initializeVars method as :
public void initializeVars(){
BUeasycounter= (Button) findViewById(R.id.BUeasycounter);
BUrps = (Button) findViewById(R.id.BUrps);
}

public void initializeVars(){
Button BUeasycounter= (Button) findViewById(R.id.BUeasycounter);
Button BUrps = (Button) findViewById(R.id.BUrps);
}
You define two button in this method but these are local variable whose scope lies between this block.
You can not access outside from this. You have initialize the local variable but instance button variable
still have null.To get solution from NPE you should write as
public void initializeVars(){
BUeasycounter= (Button) findViewById(R.id.BUeasycounter);
BUrps = (Button) findViewById(R.id.BUrps);
}
From above method it assign the reference in instance variable its scope till this class exist.
and last remove semi colon from end of switch block.

Related

Buttons outside the onCreate

Always in my apps I added buttons in void onCreate, but now I'm trying to do app with more buttons (about 10). I would like to all buttons active on start app.
In my opinion it is too much buttons to add in this onCreate and app will be starting to long.
I tried to put this:
myButton.setOnClickListener(new View.OnClickListener() {
public void onClick(View view) {
myMethod();
}
})
out of onCreate
but AndroidStudio underlines setOnClickListener and view
I don't have ideas, how and where can i add button out of onCreate.
If you don't want to overcrowd your oncreate method, then create a clicklistener outside onCreate anywhere in activity and in onCreate just set it.
onCreate :
edit_a_member = (Button) findViewById(R.id.edit_member);
delete_a_member = (Button) findViewById(R.id.delete_member);
edit_a_member.setOnClickListener(handleClick);
delete_a_member.setOnClickListener(handleClick);
clickListener:
private View.OnClickListener handleClick = new View.OnClickListener() {
#Override
public void onClick(View view) {
switch (view.getId()) {
case R.id.edit_member:
member_selected = EDIT_MEMBER_SELECTED;
callDialog();
break;
case R.id.delete_member:
callDeleteAlert();
break;
}
}
};
You can simply add a separate method for your buttons in the same class, e.g.:
public void onCreate(...){
//Standard setup of views or whatever you want to do here
this.addButtons();
}
private void addButtons(){
Button b1 = new Button("Hi");
b1.setOnClickListener(new View.OnClickListener() {
public void onClick(View view) {
myMethod();
}
});
Button b2 = new Button("Hi to you too");
b2.setOnClickListener(new View.OnClickListener() {
public void onClick(View view) {
myMethod();
}
});
}
This is an example. You can do this in soooo many ways. I feel like you should thoroughly learn Java's fundamental Object Oriented programming, because that's really what your question suggests you don't understand. Go follow a youtube tutorial. I always like "The New Boston"'s Java tutorial series on youtube.
PS: You can make code like this beautiful under the 'Words of wisdom': Don't repeat yourself
If you have to do a lot of work in your onCreate but you are worried that the UI will take too long to load you can always post a delayed runnable to a handler so in the onCreate method put :
new Handler().postDelayed(new Runnable() {
#Override
public void run() {
//add your code here
}
},10);
what this will do is your UI will load then the code in your Runnable will be executed 10 milliseconds after your UI loads thus your app will not take too long to load the UI, even though in your case I doubt it would be necessary.
If you are declaring the buttons in xml file :
Add these properties in each button Declaration in your Xml :
android:clickable="true"
android:onClick="onClick"
And now in Activity Class create a method like this :
public void onClick(View v){
switch(v.getId){
case R.id.{buttons_id_in_xml}
(Your Code)
break;
(Like for others)
}
}
If you want to add buttons dynamically :
Create a method to add the button like this:
void addButton(String buttonName, int button id){
Button button = new Button(this);
button.setText("Push Me");
(add it to parent Layout of xml)
button.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
switch(id){
case id1:
(handle )
break;
(like for others)
}
}
});
}
The best way to do this is:
add implements View.OnClickListener to
public class MainActivity extends AppCompatActivity implements View.OnClickListener {
// declare variables
private Button mBtn1;
private Button mBtn2;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_start);
// make an instance to the btns
mBtn1 = findViewById(R.id.btn1);
mBtn2 = findViewById(R.id.btn2);
// set onClickListener
mBtn1.setOnClickListener(this); // with "this" you are passing the view
mBtn2.setOnClickListener(this);
}
// implement onClick
#Override
public void onClick(View view) {
// check which btn was clicked by id
switch (view.getId()) {
case R.id.btn1:
btn1Clicked();
break;
case R.id.btn2:
btn2Clicked();
break;
}
}
private void btn1Clicked() {
// your code btn1 clicked
}
private void btn2Clicked() {
// your code btn2 clicked
}
Hope this helped. Cheers!

Android is confusing the functions of 3 different buttons

I'm currently making an app that will play some music.
There will be multiple activities, one for each song. There are usually 3 buttons per screen: One to play/pause the music, one for going to the previous page, and one for going to the next page.
Currently, Android is confused about which buttons are supposed to do what. When I click on the 'Play Music' button, the app attempts to take me to the next screen. When I click on the 'Next Page' button, it brings me to the previous page. When I click on the 'Last Page' button, it plays/pauses the song.
This is my java code for the relevant activity.
package net.jacksonhamilton.calmingmusic;
import android.app.Activity;
import android.content.Intent;
import android.media.MediaPlayer;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.view.View.OnClickListener;
import android.widget.TextView;
public class Rush extends Activity {
Button btnRush, btnRushtoCivil, btnRushtoNeil;
MediaPlayer tomsawyer;
int playing;
/** Called when the activity is first created. */
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.rush);
btnRush = (Button) findViewById(R.id.btnRush);
btnRushtoCivil = (Button) findViewById(R.id.btnRushtoCivil);
btnRushtoNeil = (Button) findViewById(R.id.btnRushtoNeil);
btnRush.setOnClickListener(btRush);
btnRushtoCivil.setOnClickListener(btRushtoCivil);
btnRushtoNeil.setOnClickListener(btRushtoNeil);
tomsawyer = new MediaPlayer();
tomsawyer = MediaPlayer.create(this, R.raw.tomsawyer);
playing = 0;
// TODO Auto-generated method stub
}
Button.OnClickListener btRush = new Button.OnClickListener(){
#Override
public void onClick(View v) {
// TODO Auto-generated method stub
switch (playing) {
case 0:
tomsawyer.start();
playing = 1;
btnRush.setText("Pause 'Tom Sawyer', by Rush");
break;
case 1:
tomsawyer.pause();
playing = 0;
btnRush.setText("Play 'Tom Sawyer', by Rush");
break;
}
}
};
Button.OnClickListener btRushtoCivil = new Button.OnClickListener(){
#Override
public void onClick(View v) {
// TODO Auto-generated method stub
tomsawyer.stop();
startActivity(new Intent(Rush.this, Splash.class));
}
};
Button.OnClickListener btRushtoNeil = new Button.OnClickListener(){
#Override
public void onClick(View v) {
// TODO Auto-generated method stub
tomsawyer.stop();
startActivity(new Intent(Rush.this, Neilyoung.class));
}
};
}
I've checked the IDs in the XML layout file, both graphically and in code. All buttons are assigned the proper IDs and the proper string value (for the text on the buttons).
I have the app set to require SDK15 as the minimum, and it is targeted to SDK19. It is also compiling with SDK19.
If it matters, I am developing the app in Eclipse Mars.
If you'd like to see the app for reference, here is a picture of the Activity.
You must have messed something up in the layout file, or you may be running some old version of the app. It sometimes happens in Eclipse that it does not rebuild the app but starts a last built version instead. Try deleting the app from the device/emulator, restarting the emulator, cleaning project or restarting IDE.

AIDE: No access to variable C and Understanding Default Code?

I am pretty new to this but I have a couple of questions which may seem silly but I would really appreciate an answer. They are located right below the code block.
package com.mycompany.myapp;
import android.app.*;
import android.os.*;
import android.view.*;
import android.widget.*;
import android.view.View.*;
public class MainActivity extends Activity
{
/** Called when the activity is first created. */
#Override
public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
Button b = (Button) findViewById(R.id.button);
b.setOnClickListener(new OnClickListener() {
public void onClick(View p1) {
((TextView)findViewById(R.id.txtview)).setText(getDiag(40));
}
});
Button c = (Button) findViewById(R.id.button2);
b.setOnClickListener(new OnClickListener() {
public void onClick(View p1) {
((TextView)findViewById(R.id.txtview)).setText(getDiag(5));
}
});
}
public String getDiag(int n){
String spaces = "";
String finalstring = "";
for(int i = 0; (i <= n); i++){
spaces += " ";
finalstring += spaces + "*" + "\n";
}
return finalstring;
}}
So, to be clear about what my questions are:
1) What is this whole default method created by AIDE? Is it always required or can I also just write my usual java and run my methods without all the UI?
2) I have a problem somewhere with brackets, everything works fine until I added button c. I have no idea where exactly to place it, with the current code AIDE tells me it has no acess to the variable c. And where is the ")" on line 25 coming from?
you can code it yourself, however you want
There is no access to Button c click because u made a small mistake:
Replace b into c at setOnClickListener:
Button c = (Button) findViewById(R.id.button2);
b.setOnClickListener(new OnClickListener() {
public void onClick(View p1) {
((TextView)findViewById(R.id.txtview)).setText(getDiag(5));
}
});
Should look like:
Button c = (Button) findViewById(R.id.button2);
c.setOnClickListener(new OnClickListener() {
public void onClick(View p1) {
((TextView)findViewById(R.id.txtview)).setText(getDiag(5));
}
});
To answer question 1:
The default structure provided is the methods that give the lifecycle of an Android Application. They are defined to provide the flow for your App.
You can use service to write your java code without UI.
You can modify your button placement in the AndroidManifest.xml and check that you indeed have a button2.
Can you also provide a more detailed error.
I cannot see your line 25 but if you are talking about the onclickListener it is the signature for an anonymous class/interface implementation.

What's wrong with my OnClickListener?

I have this jokes app on Google Play (Punny Jokes) and to get a joke, the user must tap anywhere on the screen, then on the joke screen, they get to read the joke. But when they want another joke, they must go back to the main screen and press the screen again, which tends be annoying. I'm trying to set up another full-screen button on the joke screen activity, so they don't have to go back. The jokes are in strings in I have code that selects a random random string in a class called "StartingPoint". Thanks so much!
public class DisplayMessageActivity extends Activity implements OnClickListener {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_display_message);
**//ERROR BEGINS HERE**
Button next;
Button next = (Button) = findViewById (R.id.next);
next.setOnClickListener(this);
**//ERROR ENDS HERE**
initTypeface1();
}
#Override
public void onClick(final View v) {
switch(v.getId()){
case R.id.next:
IntentHandler.switchActivity(DisplayMessageActivity.this,
StartingPoint.class, false);
break;
// TODO Auto-generated method stub
}
}
};
You have declared the field next twice. And you had an equal sign in a completely wrong place.
Button next = (Button) findViewById (R.id.next);
next.setOnClickListener(this);
or
Button next;
next = (Button) findViewById (R.id.next);
next.setOnClickListener(this);
and solution is also in this block
//ERROR BEGINS HERE
Button next;
next = (Button) findViewById(R.id.next);
next.setOnClickListener(this);
//ERROR ENDS HERE
do replace your code as above
Well you should modify code like this
Button next = (Button) findViewById (R.id.next);
and why do you use next value twice??

Android Development: Passing a parameter into an onClickListener()

Basically I am creating buttons within a for loop, I need each button to return a different value when pressed.
I had thought that creating my own onClickListener() and passing in the data needed as a parameter when it is initialized would work. It appears there are no syntax errors with what I came up with but when a button is clicked at run time the app crashes.
Heres a simplified version of what I've got thus far.
int counter = 1;
for( Program element : someList)
{
//some other code for dynamically creating textviews to stick the buttons in
//code which creates the buttons on the fly
moreInfo = new Button(this);
moreInfo.setText("More Info");
moreInfo.setOnClickListener(new DynamicOnClickListener(counter));
counter++;
}
The custom listener class
import android.util.Log;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Toast;
public class DynamicOnClickListener implements OnClickListener
{
int counter;
public DynamicOnClickListener(int acounter) {
this.counter = acounter;
}
public void onClick(View v) {
Log.v("DynamicOnClickListener","1");
Toast.makeText(v.getContext(), counter, Toast.LENGTH_LONG).show();
}
}
So in theory if this worked each button would return a different number, hope that makes sense.
Toast.makeText takes string resource id as a second argument. Your counter value is not a valid resource id that's way you are getting an error. You need to pass a String instead of int and it will work.
Toast.makeText(v.getContext(), String.valueOf(counter), Toast.LENGTH_LONG).show();
Instead of creating multiple listeners you can use setTag()
moreInfo = new Button(this);
moreInfo.setText("More Info");
moreInfo.setTag(new Integer(counter));
moreInfo.setOnClickListener(new DynamicOnClickListener();
then, in your listener
public void onClick(View v) {
Log.v("DynamicOnClickListener","1");
Toast.makeText(v.getContext(), ((Integer)v.getTag()).toString(), Toast.LENGTH_LONG).show();
}

Categories

Resources