First I must say that I'm not good in English and "completely new" to Android Programming.
I want to create an app that can monitor server performance. I have use the navigation drawer as my app interface. Each have a few fragment running with different sets of activity. One of the fragment, I would like to create an activity that can calculate the server performance using some if else statement calculation with a button to submit the results. When I run my app, I have trouble with this fragment (FuzFragment) where my app stopped immediately with an error "Unfortunately, ServerMonitorApp has stopped".
Below, is the fragment class (FuzFragment) that I used to display the layout:
package com.example.servermonitorapp;
import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Button;
import android.widget.EditText;
import android.widget.LinearLayout;
import android.widget.TextView;
public class FuzFragment extends Fragment {
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
if (container == null) {
return null;
}
LinearLayout mLinearLayout = (LinearLayout) inflater.inflate(R.layout.fragment_fuz,
container, false);
Button sumButton = (Button) mLinearLayout.findViewById(R.id.submitButton);
sumButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
EditText cpu = (EditText) v.findViewById(R.id.textCPU);
EditText ram = (EditText) v.findViewById(R.id.textRAM);
TextView res = (TextView) v.findViewById(R.id.txtResult);
int cpuslow = Integer.parseInt(cpu.getText().toString());
int cpusmedium = Integer.parseInt(cpu.getText().toString());
int cpushigh = Integer.parseInt(cpu.getText().toString());
int ramlow = Integer.parseInt(ram.getText().toString());
int rammedium = Integer.parseInt(ram.getText().toString());
int ramhigh = Integer.parseInt(ram.getText().toString());
if (cpuslow > 0 && cpuslow <= 30 | ramlow > 0 && ramlow <= 23) {
res.setText("Safe");
} else if (cpusmedium > 30 && cpusmedium <= 60 | rammedium > 23 && rammedium <= 38) {
res.setText("Risk");
} else if (cpushigh > 60 | ramhigh > 38) {
res.setText("Very Risk");
} else {
res.setText("Invalid Number");
}
}
});
return mLinearLayout;
}
}
Is there any wrong with my code that can cause my app stopped responding? Need help so much on this since I'm still in learning in Android programming.
Welcome to Android the dark side of development haha ;).
Ok let's go through a few basics.
The onCreate method is used to inflate or draw your layout. prior to having your layout drawn (if you do a findViewById) it won't exist.
In order for the onCreate method to draw the picture it needs the setContent method called that is created by default. This should be one of if not the first line of code you call. It ensures everything is available after that line for UI related interactions of an ACTIVITY. Emphasis on activity because the rules change when you get into fragments.
Now, the next issue is you have bloated code. Doing things like.
EditText myText = findViewById(R.id.myText);
int myValue = Integer.parseInt(myText.getText.toString());
etc.. can all be done in the same line and you are not using the reference to myText anywhere else so just do it like:
int myValue = Integer.parseInt(findViewById(R.id.myText).getText.toString());
Keep in mind I am doing Pseudo code. Please don't be that person that replies with " you have an error in your code " haha or I will not help.
Next up, it appears you never did the setContentView method in your onCreate, please put that back and set the content to your activity.xml code that matches the layout that you are inflating.
Next up, you are doing findViewById inside a button click. This is unnecessary repeat code. If you need to use the textView over and over then store a reference to it to avoid the repetitive lookup.
class MyClass{
EditText myTextBox;
protected void onCreate(stuff){
myTextBox = findViewById(R,id.myTextBox);
findViewById(R.id.myButton).setOnClickListener(new OnClickListener()){
#Override
protected void onClick(){
int myValue = Integer.parseInt(myTextBox.getText().toString());
}
});
}
Also for the record the onCreate should be very clean and to the point. I typically have a syncUI method that does my findViewById calls "prior to data binding days". I don't do that anymore, but new guys learning is fine.
Then in my syncUI I call wrapper methods to handle click listening instead of nesting in onCreate, but for now you are learning. But if you want a quick example..
onCreate(){
setContentView(myViewPointer from the R File);
syncUI();
}
private void syncUI(){
//SETUP TEXTVIEWS OR OTHER UIs that you need
//get btnSubmit reference from findViewByid
btnSubmit_onClick(); //called one time in onCreate to wrap the click listener into method that allows it to collapse and be easily found.
}
private btnSubmit_onClick(){
btnSubmit.setOnClickListener(new OnClickListener(){
#Override
protected void onClick(){
//handle Clicks
}
});
}
Thanks Sam for your reply..
I hv figure out one of my issue that cause my fragment stop responding when I run my app is might due to I mistaken declare my layout as LinearLayout in code above where else my actual layout in the myfragment.xml file is in Relativelayout (shown below).
LinearLayout mLinearLayout = (LinearLayout) inflater.inflate(R.layout.fragment_fuz,
container, false);
After I correct it my app can be open and the fragment related above also able to open. Only there's still problem when I try to run the code using few number sample and my app stop responding with same error "Unfortunately, ServerMonitorApp has stopped".
Related
I am trying to make an simple button that will cooperate with TextView, array and method changer (in public class Change). However the application uses the method changer only twice (below). It should work on every click. The changer method is used for the change in displayed array.
1-click: 1 |
2-click: 4 |
3-click: 1 |
4-click: 1 |
...-click: 1 |
I don't know where is the problem.
My target solution should be 1,4,1,4,1,4 ...
MainActivity.java
import androidx.appcompat.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.TextView;
public class MainActivity extends AppCompatActivity {
String[] numbers = {"1", "2","3","4"};
private Button mButton;
int i = 0;
Change ch = new Change();
TextView text;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mButton = (Button) findViewById(R.id.button2);
text = (TextView) findViewById(R.id.tv1);
ch = new Change();
mButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
text.setText(numbers[0]);
numbers = ch.changer(numbers);
i++;
}
});
}
}
Change.java
public class Change {
String[] arraynew = new String[4];
public String[] changer(String[] array){
arraynew[0]=array[3];
arraynew[1]=array[2];
arraynew[2]=array[1];
arraynew[3]=array[0];
return arraynew;
}
}
The arraynew variable in your code is global - so it will not create a new array every time you call the changer method, only rearranges its contents.
Here comes the tricky part: When you call the method for the second time, the parameter is the same object as arraynew. So when you do arraynew[0]=array[3] it changes 4 to 1 on the first slot; but arraynew[3]=array[0] will copy that newly changed 1 to the third index (where it is still the same 1 you put there). It basically eliminates the 4, making it impossible to recover.
Solution: Make arraynew local. If you declare it in the method, it will never be the same array, so the issue won't appear.
I need to add a new feature in my app and I have to put an image on the side of the layout. Such that the feature gets highlighted.
But, even if I write the code to make the view's visibility gone after one click. It still appears next time, when the app gets opened.
So, can anyone tell me how to do this correctly ??
Thanks in advance.
This code should solve your problem
public class MainActivity extends AppCompatActivity {
private ImageView imgTarget;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
SharedPreferences sharedPreferences = getSharedPreferences("app_prefs",MODE_PRIVATE);
boolean imageVisible = sharedPreferences.getBoolean("img_visible",true);
Button button = findViewById(R.id.button);
imgTarget = findViewById(R.id.imgTarget);
if (!imageVisible){
imgTarget.setVisibility(View.GONE);
}
button.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
if(imageVisible){
imgTarget.setVisibility(View.GONE);
sharedPreferences.edit().putBoolean("img_visible",false).apply();
}
}
});
}
}
I hope it helps you.
Is your app connected to a database like sql, firebase or something else, if so you can create a counter variable in your database and control your view accordingly .
Based on your description, i'm guessing you've the gone after 1 click part done already.
Use SharedPreferences to see if the app has already been opened.
If yes, then set the Visibility to View.GONE in onCreate after you find the id. Otherwise, show it. Feel free to ask if there's anything else.
I am new to android programming and am building a quiz app in which a question has 4 options and if the user clicks on one of the options the other options should be unclickable. I am currently able to only make a single button unclickable. Here is the java code.
package com.example.android.quiz;
import android.graphics.Color;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.TextView;
public class MainActivity extends AppCompatActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
}
//This method is called when option 1 of question 1 is selected
public void verifyQuestion1Option1(View view) {
Button QuestionOption1 = (Button) findViewById(R.id.question1_option1);
QuestionOption1.setBackgroundColor(getResources().getColor(R.color.solid_red));
question1Answer();
}
public void verifyQuestion1Option2(View view) {
Button Question1Option2 = (Button) findViewById(R.id.question1_option2);
Question1Option2.setBackgroundColor(getResources().getColor(R.color.solid_red));//solid red is not a predefined colour. It is declared in colors.xml
question1Answer();
}
public void verifyQuestion1Option3(View view) {
Button Question1Option3 = (Button) findViewById(R.id.question1_option3);
Question1Option3.setBackgroundColor(getResources().getColor(R.color.solid_green));
question1Answer();
}
public void verifyQuestion1Option4(View view) {
Button Question1Option4 = (Button) findViewById(R.id.question1_option4);
Question1Option4.setBackgroundColor(getResources().getColor(R.color.solid_red));//We call the getResources() method because R.colour.solid_red passed the id of the color not the actual colour value.
question1Answer();
}
public void question1Answer() {
TextView q1Answer = (TextView) findViewById(R.id.question1_answer);
String answer = "Rajinish Kumar is the current Chairman of SBI who took over after Arundhati Bhattacharya retired on 6 October.Shikha Sharma is the Managing Director and CEO of Axis Bank and Chanda Kochhar is the managing director and CEO of ICICI Bank";
q1Answer.setText(answer);
}
}
Either you can use a buttongroup which will have only 1 active button at any point of time or else, you need to disable other button programatically.
To disable the button you can use the following code:
Button button = (Button) findViewById(R.id.button);
button.setEnabled(false);
You can use .setEnabled(false); to disable a button. That button will grey out and does not respond to click events any more.
To disable all buttons, get the handle to each button and set them to disabled.
Button Question1Option1 = (Button) findViewById(R.id.question1_option1);
Button Question1Option2 = (Button) findViewById(R.id.question1_option2);
Button Question1Option3 = (Button) findViewById(R.id.question1_option3);
Button Question1Option4 = (Button) findViewById(R.id.question1_option4);
Question1Option1.setEnabled(false);
Question1Option2.setEnabled(false);
Question1Option3.setEnabled(false);
Question1Option4.setEnabled(false);
That way, all buttons of this question become disabled.
You can also come up with a solution where you save that the button is already pressed and ignore further click events. You could introduce some sort of variable bool question1answered = false; that is set to true as soon as the onClick event is fired.
public void verifyQuestion1Option4(View view) {
if (question1Answered == true) {return;}
question1Answered =true;
//Do the rest of your checks here
}
Two tips for for programming Java:
Java (in contrast to i.e C#) used lower letter variables as convention.
Button question1Option1 = (Button) findViewById(R.id.question1_option1); would be a better way.
If you have more questions, it would make sense to put them in some sort of array and reuse the same four buttons multiple times. That would save you much programming overhead and code rewrites if you have to change something. And it keeps the code cleaner.
I used to have some experience with developing for android but I started up again after 6 months and forgot most of it. I am now using a macbook to do my developing on and had to set up Eclipse, the Android SDK and AVD all over again and I'm worried I messed something up.
When I start a new project with the default activity that displays "Hello World" on my screen the app runs fine. I then tried to put in two buttons that cause the text in a new TextView to change. But whenever I include the textView part I get a runtime error. When I comment it out, the app runs but obviously nothing happens. Based upon the tutorials I've been reading, this is the appropriate place and way to declare/create the textView but I can't figure out what's wrong. Any suggestions?
[Edit] I was messing around and found that I can make the mytext a field instead of a TextView and that worked. So in my onCreate(), I put
mytext = (TextField)findViewById(R.id.TextView1);
but that doesn't seem the right way to do things.
import android.app.Activity;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.TextView;
public class IntroActivity extends Activity {
TextView myText = (TextView)findViewById(R.id.textView1);
//i've tried this with final added on to it as well (recommended by eclipse)
/** Called when the activity is first created. */
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
setButtonClickListener();
}
private void setButtonClickListener() {
Button button1 = (Button)findViewById(R.id.button1);
Button button2 = (Button)findViewById(R.id.button2);
button1.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
myText.setText("Hello");
}
});
button2.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
// myText.setText("Goodbye");
}
});
}
}
This:
TextView myText = (TextView)findViewById(R.id.textView1);
should be separated. The declaration should be at the same place:
private TextView myText;
But the assignment should come only after setContentView:
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
myText = (TextView)findViewById(R.id.textView1);
This is done since before setContentView, Dalvik doesn't know from which layout to take the view that matchs the id R.id.textView1
In short, I'm working on a "DurationPickerDialog" that works similarly to how the DatePickerDialog works but works based on the xsd:duration type, so the user specifies the number of years, months, days, etc.
I've also implemented a "fuzzy duration" function that gives me durations as a string like "one month ago". I would really like to be able to update the DurationPickerDialog's title in the same manner that the DatePickerDialog's title is updated, but there seems to be a problem. In the DatePickerDialog, they have it set to be a single line all the time, so that it doesn't get "jumpy." Here's how Android's source does the DatePickerDialog's title.
// Note: before the skim-readers look at this bit, realize that this is NOT my
// code but Android's internal code for the DatePickerDialog.
#Override
public void show() {
super.show();
/* Sometimes the full month is displayed causing the title
* to be very long, in those cases ensure it doesn't wrap to
* 2 lines (as that looks jumpy) and ensure we ellipsize the end.
*/
TextView title = (TextView) findViewById(R.id.alertTitle);
title.setSingleLine();
title.setEllipsize(TruncateAt.END);
}
Unfortunately, I cannot access their R.id.alertTitle, because it is part of com.android.internal.R.
I have seen implementations like this stackoverflow post where it would have me modify the Window.FEATURE_CUSTOM_TITLE attribute, but that doesn't seem to let me modify the title (easily) after that.
There was also another stackoverflow post that mentioned how to change the title at runtime between two different XML layouts, but that also doesn't seem like it would be all too helpful, since the title should be modified every time the duration changes, and creating an XML layout for each duration is obviously not a good idea.
So, since they "cheated" by accessing a value that us mere mortals don't have access to, is there another way that I could go about doing it?
Edit: And through some black magic, it seems that it now does ellipsize the text like I was wanting? Only earlier it wasn't, and now I can't seem to reproduce the problem. So, I suppose while we're at it, can someone explain to me how I might have accomplished this magic?
I would implement a custom dialog by extending the Dialog class and creating a custom xml layout for it.
You'd need some custom button backgrounds for the plus / minus and top / bottom combos and some button listeners to manipulate the values.
Since you are going for a duration value, you are probably going to need more space than the existing dialog gives you anyway.
This way you can set the title to whatever you like. Let me know if you need a code example.
Example:
The dialog class:
import android.app.Dialog;
import android.content.Context;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.TextView;
public class DurationDialog extends Dialog {
private Button yearButtonPlus;
private Button yearButtonMinus;
private TextView dialogBody;
private TextView dialogTitle;
private String dialogBodyString;
private String dialogTitleString;
public DurationDialog(final Context context, String dialogBody, String dialogTitle) {
super(context,R.style.CustomDialogTheme);
this.dialogBodyString = dialogBody;
this.dialogTitleString = dialogTitle;
}
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
this.setContentView(R.layout.my_dialog);
yearButtonPlus = (Button) findViewById(R.id.dialog_year_button_plus);
yearButtonMinus = (Button) findViewById(R.id.dialog_year_button_minus);
dialogBody = (TextView) findViewById(R.id.dialog_body);
dialogTitle = (TextView) findViewById(R.id.dialog_title);
dialogBody.setText(dialogBodyString);
dialogTitle.setText(dialogTitleString);
yearButtonPlus.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
//do year increment here
}
});
//etc...
}
}
In your activity, you call this.showDialog(DURATION_DIALOG); // DURATION_DIALOG is just an integer specified at the top of your Activity to identify the dialog for the next peice of code, which handles actually creating the dialog:
import android.app.Activity;
import android.app.Dialog;
public class MyActivity extends Activity {
private Dialog dialog;
//Lots of other activity stuff...
protected Dialog onCreateDialog(int id) {
switch (id) {
case DURATION_DIALOG:
dialog = new DurationDialog(Activity.this, "your title", "your body");
dialog.setOnDismissListener(onDismissListener);
break;
default:
dialog = null;
}
return dialog;
}
}
//put this listener in as an inner class of MyActivity:
private DialogInterface.OnDismissListener onDismissListener = new DialogInterface.OnDismissListener() {
#Override
public void onDismiss(DialogInterface dialog) {
DurationDialog dialog = (DurationDialog) dialog;
//grab the duration stuff out of your dialog and do stuff with it....
}
};
Finally, you can set your dialog theme as is done above in your styles.xml file. For example:
<?xml version="1.0" encoding="utf-8"?>
<resources>
<style name="CustomDialogTheme" parent="#android:style/Theme.Dialog">
<item name="android:windowBackground">#drawable/bgnd_transparent</item>
<item name="android:windowIsFloating">true</item>
</style>
</resources>
Good luck!
If you want to modify the dialog title's TextView (change text, style, behaviour...) without using a custom view, just do it that way:
TextView tv = (TextView) dialog.findViewById(android.R.id.title);
tv.setText("New title");
...