so I want to create a Rock Paper Scissors app that should work like this:
In the first screen you enter the names of the 2 players.
In the second screen there are the names of the players and the score of each player near it.The progress is that you need to click a button,and after you click it,in each player's side,random image(rock paper or scissors) will appear and the winner will get a point,or nobody will if its a draw.
NOTE:This might not be an error in the code based on what i've seen when I tried to search for the message i'm getting while debugging so you may want to look at it first.
I would appreciate some comments on the code though.
I checked if the names that i'm passing from the first activity to the second one before I had started to work on the button and the app worked fine.
But after I wrote the code for the OnClickListener, the app just crashes instantly after the first activity when I run it. It is my first time working with images like that so i'm not sure that if used it properly. I have created some functions so the code will be more readable without knowing exactly what i'm doing though because i'm pretty new to android.
first activity:
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Button startBtn;
startBtn = findViewById(R.id.startBtn);
startBtn.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
EditText p2Name=findViewById(R.id.p2EditText);
EditText p1Name=findViewById(R.id.p1EditText);
String name1=p2Name.getText().toString();
String name2=p1Name.getText().toString();
Intent intent1 = new Intent(MainActivity.this, Game.class);
intent1.putExtra("name1",name1);
intent1.putExtra("name2",name2);
MainActivity.this.startActivity(intent1);
}
});
}
second activity
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_game);
String p1Name;
String p2Name;
if (getIntent().hasExtra("name1")) {
p1Name = getIntent().getStringExtra("name1");
TextView p1NView = findViewById(R.id.p1);
p1NView.setText(p1Name);
}
if (getIntent().hasExtra("name2")) {
p2Name = getIntent().getStringExtra("name2");
TextView p2NView = findViewById(R.id.p2);
p2NView.setText(p2Name);
}
Button NRound=findViewById(R.id.newRoundBtn);
NRound.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
TextView score1=findViewById(R.id.score1View);
TextView score2=findViewById(R.id.score2View);
int p1Score = Integer.parseInt(score1.getText().toString());
int p2Score = Integer.parseInt(score2.getText().toString());
String[] RPS = new String[]{"rock", "paper", "scissors"};
Random r = new Random();
String p1Hand;
String p2Hand;
p1Hand = RPS[r.nextInt(3)];
p2Hand = RPS[r.nextInt(3)];
showImages(p1Hand,p2Hand);
String result=findWinner(p1Hand,p2Hand);
switch (result){
case "player1":
p1Score++;
score1.setText(String.valueOf(p1Score));
case "player2":
p2Score++;
score2.setText(String.valueOf(p2Score));
if(score1.getText().equals('3') || score2.getText().equals('3')){
Intent end=new Intent(Game.this,EndScreen.class);
Game.this.startActivity(end);
}
}
}
});
update();
}
public static String findWinner(String hand1,String hand2){
if(hand1.equals(hand2)){
return "draw";
}
String both=hand1.concat(hand2);
if(both.equals("rockscissor") || both.equals("paperrock")||both.equals("scissorspaper")){
return "player1";
}else{
return "player2";
}
}
public void showImages(String hand1,String hand2){
ImageView rock1=findViewById(R.id.rock1);
ImageView paper1=findViewById(R.id.paper1);
ImageView scissors1=findViewById(R.id.scissors1);
ImageView rock2=findViewById(R.id.rock2);
ImageView paper2=findViewById(R.id.paper2);
ImageView scissors2=findViewById(R.id.scissors2);
switch (hand1){
case "rock":
rock1.setVisibility(View.VISIBLE);
case "paper":
paper1.setVisibility(View.VISIBLE);
case "scissors":
scissors1.setVisibility(View.VISIBLE);
}
switch (hand2){
case "rock":
rock2.setVisibility(View.VISIBLE);
case "paper":
paper2.setVisibility(View.VISIBLE);
case "scissors":
scissors2.setVisibility(View.VISIBLE);
}
}
public void update(){
ImageView[] images=new ImageView[6];
for (ImageView image:images)
{
if(image.getVisibility()==View.VISIBLE){
image.setVisibility(View.GONE);
}
}
}
Logs
Edit:now after I have posted and seen the logs I understood what was the problem. I forgot to initialize the imageView array in a function and I was just looping over null array,trying to get its visibility.And Now it does not crash.
I didn't know about this so thanks anyways for telling me to post it.(thought errors should show up in the console or something).
Now I am dealing with another problem,I will try to solve it on my own though.
Process: com.example.rockpaperscissors, PID: 11607
java.lang.RuntimeException: Unable to start activity ComponentInfo{com.example.rockpaperscissors/com.example.rockpaperscissors.Game}: java.lang.NullPointerException: Attempt to invoke virtual method 'int android.widget.ImageView.getVisibility()' on a null object reference
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:3260)
at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:3396)
at android.app.servertransaction.LaunchActivityItem.execute(LaunchActivityItem.java:83)
at android.app.servertransaction.TransactionExecutor.executeCallbacks(TransactionExecutor.java:135)
at android.app.servertransaction.TransactionExecutor.execute(TransactionExecutor.java:95)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:2009)
at android.os.Handler.dispatchMessage(Handler.java:107)
at android.os.Looper.loop(Looper.java:214)
at android.app.ActivityThread.main(ActivityThread.java:7319)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:492)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:934)
Caused by: java.lang.NullPointerException: Attempt to invoke virtual method 'int android.widget.ImageView.getVisibility()' on a null object reference
at com.example.rockpaperscissors.Game.update(Game.java:71)
at com.example.rockpaperscissors.Game.onCreate(Game.java:65)
at android.app.Activity.performCreate(Activity.java:7783)
at android.app.Activity.performCreate(Activity.java:7772)
at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1299)
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:3235)
at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:3396)
at android.app.servertransaction.LaunchActivityItem.execute(LaunchActivityItem.java:83)
at android.app.servertransaction.TransactionExecutor.executeCallbacks(TransactionExecutor.java:135)
at android.app.servertransaction.TransactionExecutor.execute(TransactionExecutor.java:95)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:2009)
at android.os.Handler.dispatchMessage(Handler.java:107)
at android.os.Looper.loop(Looper.java:214)
at android.app.ActivityThread.main(ActivityThread.java:7319)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:492)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:934)
I tried to debug the app and at the last line of the first activity,the message that shows up is: source code does not match the byte code.
First try to clean the project and rebuild it.
In order for us to help you with the crash, we need to see the logs. Please add that as well.
About your code:
MainActivity.class
Try validating user input before passing it to the next activity.
Game.class (assuming this is also an activity so try renaming it to GameActivity.class)
When you are retrieving data from the intent, it's best practice to create a constant and make it public that you can use in the main activity as well (if you make a typo, it's hard to find the problem)
Something like: public static final String NAME_ONE_KEY = "name1";
I don't see the need of using a string array, identify those actions by integer and comment it so you and others who read your code can understand it.
It seems like you have a lot of child elements in your game layout file
Add the images into the drawable folder, create one image view for each player and update the image source.
Finally, save the state so you don't loose the data on device rotation.
Related
I am really new at programming. I am trying to run a simple average calculator and getting a force close, this is what the logcat is showing. I am running android studio version 2.3.3
FATAL EXCEPTION: main
Process: com.vu.gradingapp, PID: 6312
java.lang.NumberFormatException: For input string: ""
at java.lang.Integer.parseInt(Integer.java:620)
at java.lang.Integer.valueOf(Integer.java:794)
at com.vu.gradingapp.AverageActivity$1.onClick(AverageActivity.java:37)
at android.view.View.performClick(View.java:6219)
at android.view.View$PerformClick.run(View.java:24482)
at android.os.Handler.handleCallback(Handler.java:769)
at android.os.Handler.dispatchMessage(Handler.java:98)
at android.os.Looper.loop(Looper.java:164)
at android.app.ActivityThread.main(ActivityThread.java:6540)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.Zygote$MethodAndArgsCaller.run(Zygote.java:240)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:767)
The code i am using is as follow
public class AverageActivity extends AppCompatActivity {
EditText editmanner, editinstances, editshortstance, editstrikes, editboxingskills, editknocks, editkicks, editResults;
Button btnResults;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.average_page);
editmanner =(EditText)findViewById(R.id.editText8);
editinstances = (EditText)findViewById(R.id.editText9);
editshortstance = (EditText)findViewById(R.id.editText10);
editstrikes = (EditText)findViewById(R.id.editText11);
editboxingskills = (EditText)findViewById(R.id.editText12);
editknocks = (EditText)findViewById(R.id.editText13);
editkicks = (EditText)findViewById(R.id.editText14);
editResults = (EditText)findViewById(R.id.editText15);
btnResults = (Button) findViewById(R.id.button10);
btnResults.setOnClickListener(new View.OnClickListener(){
#Override
public void onClick(View v) {
int first, second, third, fourth, fifth, sixth, seventh, results;
first=Integer.valueOf(editmanner.getText().toString());
second=Integer.valueOf(editinstances.getText().toString());
third=Integer.valueOf(editshortstance.getText().toString());
fourth=Integer.valueOf(editstrikes.getText().toString());
fifth=Integer.valueOf(editboxingskills.getText().toString());
sixth=Integer.valueOf(editknocks.getText().toString());
seventh=Integer.valueOf(editkicks.getText().toString());
results=(first+second+third+fourth+fifth+sixth+seventh)/7;
editResults.setText(String.valueOf(results));
}
});
}
public void knowtheresults (View view) {
String button_text;
button_text = ((Button) view).getText().toString();
if (button_text.equals("Summary")) {
Intent intent = new Intent(this, ResultActivity.class);
startActivity(intent);
} else if (button_text.equals("Back")) {
Intent intent = new Intent(this, MainActivity.class);
startActivity(intent);
WHat am I doing wrong :D
Thanks Guys
Error says you cannot convert "" value to number Its a java.lang.NumberFormatException. So use 0 instead of number is blank first check if edittext is blank than set its value to 0
int first;
if(editmanner.getText().toString().equals("")){
first = 0
}else{
first = Integer.valueOf(editmanner.getText().toString());
}
do this for your all int variables.
Update your code with such verification for each int variable:
if (editmanner().toString().isEmpty())
first = 0;
else
first = Integer.parseInt(editmanner().toString());
Since you have int variables (not Integer) it is preferable to use parseInt instead valueOf
Thanks guys, I just filled in the textedits with (0) and now is working. Please apologize for my silly questions.
Is there any way to hide this zeros on the textview so it shows blanks.
java.lang.NumberFormatException
Thrown to indicate that the application has attempted to convert a string to one of the numeric types, but that the string does not have the appropriate format.
The logcat already stated what is the cause of the crash. One or all of your EditText has empty string. To convert string to Integer, the string must be numeric(0,1,2 etc). You need to set EditText with numeric value (eg: 0).
this is my first question being asked on stackoverflow. My question is regarding variable use across different recyclable intents.
e is declared like this.
final Bundle e=getIntent().getExtras();
Here i am creating new intents for different setOnClickListener() and passing a different variable for each intent.
Intent info = new Intent(EItemListView.this, ItemInfo.class);
Bundle extras = new Bundle();
int[] a=new int[listview.getAdapter().getCount()];
if (i == 0) {
extras.putIntArray("img", n5x_images);
extras.putString("info", n5x_info);
extras.putInt("pc",a[0]);
} else if (i == 1) {
extras.putIntArray("img", op3_images);
extras.putString("info", op3_info);
extras.putInt("pc",a[1]);
}
info.putExtras(extras);
startActivity(info);
Now this is the OnClickListener() where i am trying to update the variables which i passed through the intent extras, but am unable to update those variables.
addtc.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
int c=e.getInt("pc");
c=c+1;
Log.i("Log","value "+c);
}
The log message which i get from the above method is always 1, i think the variable in c is always set to 0 and then increments by 1 and hence the log message shows 1.
I need the variables a[0],a[1],a[2], etc to pertain its increment operation.
To make it more clear, this is the java file i am using. The error is in the OnClickListener of addtc button at the bottom of this code.
public class ItemInfo extends AppCompatActivity {
private ViewAnimator viewanimator;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_item_info);
Button next=(Button)findViewById(R.id.bnext);
Button prev=(Button)findViewById(R.id.bprev);
viewanimator=(ViewAnimator)findViewById(R.id.viewAnimator);
TextView info=(TextView)findViewById(R.id.item_info);
Button addtc=(Button)findViewById(R.id.badd);
Button test=(Button)findViewById(R.id.button);
Bundle e=getIntent().getExtras();
int img[]=e.getIntArray("img");
for(int i=0;i<img.length;i++)
{
ImageView imgview = new ImageView(getApplicationContext());
imgview.setImageResource(img[i]);
viewanimator.addView(imgview);
}
info.setText(e.getString("info"));
next.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
viewanimator.showNext();
}
});
prev.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
viewanimator.showPrevious();
}
});
addtc.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
int c=e.getInt("pc");
c=c++;
Log.i("Log","value "+c);
}
});
}
}
Thanks in advance!!!
Your approach is wrong. You cannot do this in this way. Your understanding of what an "extra" in an Intent is incorrect.
When you do this:
extras.putInt("pc",a[1]);
This adds an "extra" to the extras Bundle. The Bundle is simply a key/value pair map and you have added an entry that contains the key "pc" and the value is whatever a[1] is. It puts a copy of the value of a[1] into the Bundle, it does not put a reference to a[1] in the Bundle.
Therefore, if a[1] is 5 when you add it to the extras Bundle, a[1] will always be 5 and will never be changed to anything else.
You can't do this in this way.
Alternative: Depending on your application architecture and what you are trying to do, you can use one of the following methods:
1) Use startActivityForResult(), pass the data from one Activity to another, have the second Activity update the data and put it back into the Intent which is then returned to the "calling" Activity by using setResult().
2) Use a static variable (basically a "global" variable) to contain the data. Both activities can then access the data directly (you don't need to put the data in the Intent.
3) Put the data in a database. Both activities can then read/write from/to the database.
First advice I can give you is debugging and posting debug result. for example, are you sure that a[0] and a[1] aren't 0?
Assuming they are not, why are you declaring the bundle as final? referring to this probably final is not what you were looking for. Try removing it or replacing with private
Another suggestion is more for readable purpose, replace c = c+1; with c++; but this doesn't change the result, it just make it more linear and easier for reading.
Now after this fix (the final keyword one) tell me if something changed please :)
I am a android developer beginner, and I need some help please.
I have one activity (activity 1) with a button named "MORE", which when clicked takes me to another activity. This works well.
And I have another activity (activity 2). When I click on one checkbox, I need to make the button "MORE" invisible in the activity 1.
I found other similar questions, but it is throwing an error and I couldn't figure it out.
I made the button static in the activity 1
public static Button btn2;
In the activity 2 I set it to invisible
public void onClick(View view) {
Intent i;
switch (view.getId()) {
case R.id.checkBox2:
// set invisible button more in stock quotes
StockDetail.btn2.setVisibility(View.INVISIBLE);
break;
default:
break;
}
}
It is throwing this error:
java.lang.NullPointerException: Attempt to invoke virtual method 'void android.widget.Button
I found a similar question in this link:
Android: Hide button from another activity
I did exactly like that, but it still does not. I appreciate if someone can help me. Thank you
I think you should save a variable such as isShow (boolean) by SharePreference file. When you open activity1, you will get value at the sharepreference file.
Such as: If it is true --> you will set visible for button.
DO NOT make any variable static that may use context (like your button) as it may be highly susceptible to memory leaks. Usually there are various design patterns in place to avoid these.
A simple solution for your case can be starting your Activity2 from Activity1 using startActvityForResult(). In this setup the Activity1 expects some kind of result from Activity2. In your case it would be the state of your button. To learn more about it visit this [very small] official training doc: Getting a Result from an Activity.
Let us know if you tun intoo any issues.
you can apply a null point check like this
if(StockDetails.btn2 != null)
{
StockDetails.btn2.setVisiblity(View.Gone);
}
This will not work until StockDetail will be created. Alternatively for that you can do make a static variable inside StockDetail class like below:-
public class StockDetail extends Activity{
public static int buttonVisibility=View.VISIBLE;
#override
public void onCreate(Bundle savedInstanceState){
setContentView(R.layout.act2);
Button btn=(Button)findViewById(R.id.btn);
btn.setVisibilty(buttonVisibility);
}
and from Activity1
public void onClick(View view) {
Intent i;
switch (view.getId()) {
case R.id.checkBox2:
// set invisible button more in stock quotes
StockDetail.buttonVisibility=View.INVISIBLE;
break;
default:
break;
}
}
try the above it may help you.
public class Menu extends Activity {
/** Called when the activity is first created. */
public void onCreate(Bundle icicle) {
//myIntent.setClassName("hello.World", "hello.World.mybuttonclick");
// myIntent.putExtra("com.android.samples.SpecialValue", "Hello, Joe!"); // key/value pair, where key needs current package prefix.
//startActivity(myIntent);
//Button myButton = (Button) findViewById(R.id.my_button);
super.onCreate(icicle);
setContentView(R.layout.main);
}
public void updateLayout(){
Intent myIntent = new Intent(Menu.this, mybuttonclick.class);
startActivity(myIntent);
// TextView sayHello = (TextView) findViewById(R.id.Hello);
}
}
Hey guys, I am a new android java student and we have to develop a simple hello world app.. I am finding some difficulty getting my onClick() activity to work, using android:Onclick in xml.. what i am trying to do is change the content view do display a simply a different layout and saying hello.. i am using setContentLayout to do this, every time i click said button tho the android app crashes out.. am i doing something wrong?
regards,
Stefan
When you set a click listener in xml you must have the method defined inside the activity you are clicking in. Lets say you set the onClick in xml to be "buttonClicked", you must create a method looking exactly like the one below.
public void buttonClicked(View view)
{
//Your code here
}
The thing to notice is that the method is a public void with only a single parameter of type View. XML defined click listeners must be like this to work. The view object in the example above is the view that was clicked.
You update layout function needs to read
public void updateLayout(View view)
In response to your question, there are a number of things that are issues causing the complication that you described. Let it first be said, that you don't have to do anything any particular way, provided that you make concessions for certain things. Android is a very flexible platform and Java, as an OOP language allows you to do things that many non OOP languages do not.
Whenever you create a "clickable" item, like a Button, if you want to have your program respond, you must have something "listen" to it. This is known as a Listener. In your case, you are looking for an OnClickListener. The OnClickListener does not have to be a part of the Activity necessarily. It just has to be a class that implements View.OnClickListener. Then, you have tell the setOnClickListener() method of the Button who its listener is. The following example shows what is necessary without your declaration in XML (but it is important).
class Menu extends Activity implements View.OnClickListener
{
public void onCreate(Bundle icicle)
{ setContentView(R.layout.main);
Button btn = (Button)findViewById(R.id.BUTTON_ID_AS_DEFINED_BY_YOUR_XML);
btn.setOnClickListener(this);
}
public void onClick(View view)
{ int id = view.getId();
if (id == R.id.BUTTON_ID_AS_DEFINED_BY_YOUR_XML)
updateLayout()//Do your Click event here
}
public void updateLayout()
{ //updateLayout code...
}
}
Something that needs to be noted is the OnClick() above. Every OnClickListener must use the same signature as theOnClick() That means itmust have the same return and same arguments even if it has a different name. For what you are trying to do (in XML), you have set your android:OnClick to updateLayout. This means that `updateLayout() must be declared as follows:
public void updateLayout(View view)
Now, getting the update method to actually work: While you provide your code, we don't actually know what errors you are getting. It is always much easier to solve a problem if we have a copy of the Logcat output that includes the error you are receiving. Once, we have that we can target your error specifically and I can edit my answer to include what you may additionally need.
FuzzicalLogic
my dear friends. Could you help me to figure out where do I have memory leak in my application.
There are two activities.
In first activity I'v got a rather big static ArrayList consists of bitmaps and another needed information. I made it static, because I need to take it from another activity, and It's loading takes to much time.
In another activity, I also have one static field, using as a key for getting data which present in an Intent from previous activity.
If I try to start one activity from another and go back several times, I get shutting down VM.
To be more clear, here is a snippet of my code:
public class MoviesGallery extends Activity
{
...
private static ArrayList<Movie> films = new ArrayList<Movie>();
...
public void contextButtonsClickHandler(View v)
{
switch(v.getId())
{
case R.id.play_button:
Log.d("Context Button", "Play button has clicked");
mContextButtonHasPressed = true;
Intent filmData = new Intent(MoviesGallery.this, MovieInfo.class);
filmData.putExtra(MovieInfo.mPOS,mPOSITION_OF_CLICKED_ITEM);
startActivityForResult(filmData, 1);
break;
...
}
And this is another activity:
public class FilmInfo extends Activity
{
public static String mPOS = "pos";
private int mNumOfFilm = -1;
private LinearLayout mWall;
...
protected void onCreate(Bundle savedInstanceState)
{
Bundle extra = getIntent().getExtras();
mNumOfFilm=extra.getInt(mPOS);
...
Drawable d = new BitmapDrawable(MoviesGallery.getMoviesArray().get(mNumOfFilm).getWall()));
mWall = (LinearLayout) findViewById(R.id.Wall);
mWall.setBackgroundDrawable(d);
...
setResult(0);
}
I would suggest that potentially memory-leak point is in FilmInfo class member:
private LinearLayout mWall;
Layout has reference to Activity, which each time changes.
So to avoid keeping reference to dead Activity just use in FilmInfo class
#Override
public boolean onContextItemSelected(MenuItem item)
{
//blah-blah
mWall=null;
}
Anyway recipe is simple - try to avoid keeping objects which might contain references to Activity/Context objects.