The activity contains a lot of EditTexts (about 40) where the user enters numbers, and then they're added. But when one of these EditTexts is empty, it gives an error and the app stops. I've read lots of solutions, but I don't want to write code for each EditText.
Here is some code (Wrote 450 lines, don't gonna show them all, but all of them are similar)
EditText mark1;
EditText mark2;
EditText mark3;
EditText mark4;
EditText mark5;
TextView marksem1;
Button calcsem1;
double mark1calc=0;
double mark2calc=0;
double mark3calc=0;
double mark4calc=0;
double mark5calc=0;
double totalsem1=0;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.etsia_gia_ata_layout);
initControls();
private void initControls() {
// Course 1 sem 1 calc
mark1=(EditText)findViewById(R.id.mark1);
mark2=(EditText)findViewById(R.id.mark2);
mark3=(EditText)findViewById(R.id.mark3);
mark4=(EditText)findViewById(R.id.mark4);
mark5=(EditText)findViewById(R.id.mark5);
marksem1=(TextView)findViewById(R.id.total1calc);
calcsem1=(Button)findViewById(R.id.total1);
calcsem1.setOnClickListener(new Button.OnClickListener()
{public void onClick
(View v) {calcsem1();}
private void calcsem1() {
mark1calc=Double.parseDouble(mark1.getText().toString());
mark2calc=Double.parseDouble(mark2.getText().toString());
mark3calc=Double.parseDouble(mark3.getText().toString());
mark4calc=Double.parseDouble(mark4.getText().toString());
mark5calc=Double.parseDouble(mark5.getText().toString());
totalsem1=(9*mark1calc+6*mark2calc+6*mark3calc+6*mark4calc+3*mark5calc)/30;
marksem1.setText(Double.toString(totalsem1));
marksem1.setText(String.format("%.2f", totalsem1));
}});
}
}
Hope there's a solution. Thank you very much!
Your problem comes from the fact that Double.parseDouble(...) on an empty string will throw a NumberFormatException. You could replace each line with somthing like this:
try {
mark1calc = Double.parseDouble(mark1.getText().toString());
} catch (NumberFormatException e) {
mark1calc = 0;
}
This is a lot of extra code, so I'd suggest implementing something like this:
public static Double safeParse(String input) {
try {
return Double.parseDouble(input);
} catch (NumberFormatException e) {
return 0d;
}
}
// ...
mark1calc = safeParse(mark1.getText().toString());
mark2calc = safeParse(mark2.getText().toString());
mark3calc = safeParse(mark3.getText().toString());
// ...
(This assumes you want an empty box to be worth 0; you can adjust the default value to your needs)
I assume your problem is with parseDouble. You can write your own protected parseDouble, which will try-catch to parse the text, and if an exception is thrown, will just return zero.
Something like this:
private static double safeParseDouble(String text)
{
try
{
double result = Double.parseDouble(text);
return result;
}
catch (Exception ex)
{
return 0;
}
}
Double.parseDouble() can throw exceptions so you will need to use try-catch block.
try {
mark1calc=Double.parseDouble(mark1.getText().toString());
mark2calc=Double.parseDouble(mark2.getText().toString());
mark3calc=Double.parseDouble(mark3.getText().toString());
mark4calc=Double.parseDouble(mark4.getText().toString());
mark5calc=Double.parseDouble(mark5.getText().toString());
totalsem1=(9*mark1calc+6*mark2calc+6*mark3calc+6*mark4calc+3*mark5calc)/30;
marksem1.setText(Double.toString(totalsem1));
marksem1.setText(String.format("%.2f", totalsem1));
} catch (Exception e) {
// handle errors...
}
you can replace your parsing statement with terinary statement as below:
mark2calc = mark4.getText().toString().equals("") ? 0 : Double.parseDouble(mark4.getText().toString());
Related
I get NumberFormatException error at this line of my code. What should i do?
String employ = intent.getStringExtra("employeeid").trim();
spinEmployee.setSelection(Integer.parseInt(employ)-1);
You can handle this by adding try catch block.
Create one method to get valid int from string like this
public int getValidIntFromString(String inputstring) {
if (inputstring!= null) {
if (!inputstring.equals("")) {
try {
return Integer.parseInt(inputstring);
} catch (NumberFormatException e) {
// TODO: handle exception
Log.e("Error-- > ", e.toString());
return 0;
}
} else {
return 0;
}
} else {
return 0;
}
}
Now you can convert string to int by calling this
int intemploy = getValidIntFromString(employ);
Here employ will be your String from where you want to parse Int from String.
Note: if you get employ data from EditText then please set inputType="number" in xml file to avoid such kind of Exception.
Just like this
<EditText
android:id="#+id/myEditText"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:inputType="number" />
The exception says the format of EMPLOY is not valid,maybe it's a String like '2d','33a'
I need help. I just want to make application that reads battery capacity, like read in mAh/mA. Anyone can help me please?
I've read another thread about this, but I was confused because I need an integer from battery capacity. For example, my android has a battery with capacity 2500 mAh
and I need that integer of capacity(2500) where I want to include that number in my calculation.
Thanks for the help.
This is code that I want to change, I am just confused where it must be changed.
public void getBatteryCapacity() {
Object mPowerProfile_ = null;
final String POWER_PROFILE_CLASS = "com.android.internal.os.PowerProfile";
try {
mPowerProfile_ = Class.forName(POWER_PROFILE_CLASS)
.getConstructor(Context.class).newInstance(this);
} catch (Exception e) {
e.printStackTrace();
}
try {
double batteryCapacity = (Double) Class
.forName(POWER_PROFILE_CLASS)
.getMethod("getAveragePower", java.lang.String.class)
.invoke(mPowerProfile_, "battery.capacity");
Toast.makeText(MainActivity.this, batteryCapacity + " mah",
Toast.LENGTH_LONG).show();
} catch (Exception e) {
e.printStackTrace();
}
}
Yes, your code gives total mAh capacity. You can change that function to return the value like this:
public Double getBatteryCapacity() {
// Power profile class instance
Object mPowerProfile_ = null;
// Reset variable for battery capacity
double batteryCapacity = 0;
// Power profile class name
final String POWER_PROFILE_CLASS = "com.android.internal.os.PowerProfile";
try {
// Get power profile class and create instance. We have to do this
// dynamically because android.internal package is not part of public API
mPowerProfile_ = Class.forName(POWER_PROFILE_CLASS)
.getConstructor(Context.class).newInstance(this);
} catch (Exception e) {
// Class not found?
e.printStackTrace();
}
try {
// Invoke PowerProfile method "getAveragePower" with param "battery.capacity"
batteryCapacity = (Double) Class
.forName(POWER_PROFILE_CLASS)
.getMethod("getAveragePower", java.lang.String.class)
.invoke(mPowerProfile_, "battery.capacity");
} catch (Exception e) {
// Something went wrong
e.printStackTrace();
}
return batteryCapacity;
}
The getAveragePower function returns the average current
in mA consumed by the subsystem. In this case subsystem string is battery.capacity which returns the battery capacity.
See class code here:
https://android.googlesource.com/platform/frameworks/base.git/+/master/core/java/com/android/internal/os/PowerProfile.java
And if you really want that value as int, just change it like this:
int bc = getBatteryCapacity().intValue();
The logcat shows that the Integer.Parse() function was not able to convert the string to int or float whereas i have linked the xml file in java. Also, i have set the input Type of the rate and quantity column as number so there is no chance that the user can enter anything other than an int or float. Plz help. I have been trying to get this code working for a long time. But i cant find the solution.
Attached is the code:
public int initializeVars(){
int i;
for(i=0;i<9;i++){
//items[i] is the AutoCompleteTextView array
item[i]=items[i].getText().toString();
iquant[i]=Integer.valueOf(quant[i].getText().toString());
irate[i]=Float.valueOf(rates[i].getText().toString());
if(item[i]=="")
break;
}
return i;
}
}
To avoid these kind of circumstances use these two functions.
For Int
private int getIntFromString(String str){
try{
return Integer.parseInt(str);
}catch(Exception e){
return 0;
}
}
For float
private float getFloatFromString(String str){
try{
return Float.parseFloat(str);
}catch(Exception e){
return 0f;
}
}
Call these methods at required places
Try to use the parseInt method instead of valueOf and also keep that parsing code in try{}...catch{} block of NumberFormateException.
try{
iquant[i]=Integer.parseInt(quant[i].getText().toString());
irate[i]=Float.parseFloat(rates[i].getText().toString());
}
catch(NumberFormateException e){}
INT
try {
myInt = Integer.parseInt(myString);
} catch(NumberFormatException e) {
}
FLOAT
try {
myFloat = Float.parseFloat(myString);
} catch(NumberFormatException e) {
}
Maybe instead of valueOf you can try parsing it directly via
yourInt = Integer.parseInt(yourString);
youtFloat = Float.parseFloat(yourString);
I always do it this way and it works. In the float variable make sure that decimals are marked by "." not ",".
You may also want to try and catch NumberFormatException to avoid problems while parsing.
I'd like an inputType in the edit text that i can input fractional number like this: 2/4 (i want print the "/").
The program is about calculating things and i need to type fractional insted of decimal. Thanks. Sorry my bad english.
I think the best way would be to use a string for your input text, then to parse the string to figure out what kind of things the user entered.
When the user has finished their input, you can check the string with something like this:
public float testInputString(String testString) {
boolean goodInput = true;
float result = 0;
if (testString.contains("/")) {
//possible division
String pieces[] = testString.split("/");
if (pieces.length != 2) {
goodInput = false;
} else {
try {
float numerator = Float.parseFloat(pieces[0]);
float denominator = Float.parseFloat(pieces[1]);
result = numerator/denominator;
} catch (Exception e) {
goodInput = false;
}
}
} else if (testString.contains(".")) {
try {
result = Float.parseFloat(testString);
} catch (Exception e) {
goodInput = false;
}
}
//TODO something here if bad input, maybe an alert or something
return result;
}
Also, you can check while they are typing for valid input if you use a keylistener like this. You could modify that to allow only numbers . and /.
put this property in xml node of Edittext and use Double notation instead of "/"
android:digits="1234567890.-"
I am doing a program where users can use regular expressions to search in text, and I want to let the matching text to be selected. So I use this code:
public void onClick(View v) {
try {
switch (v.getId()) {
case R.id.btn_search:
Matcher m = Pattern.compile(reg.getText().toString()).matcher(txt.getText());
int start = txt.getSelectionStart();
if (start != txt.getSelectionEnd()) {
start++;
}
if (start < 0 || start >= txt.length()) {
start = 0;
}
while (true) {
try {
m.find(start);
txt.setSelection(m.start(), m.end());
txt.requestFocus();
break;
} catch (IllegalStateException ex) {
if (start == 0) {
err_notfound.show();
break;
}
start = 0;
}
}
break;
}
} catch (PatternSyntaxException ex) {
err_syntax.show();
} catch (Throwable ex) {
showException("onClick", ex);
}
}
However the code is not acting as expected. When I put the cursor manually to a position, and then press the search button, sometimes the program will set the cursor to m.start() but do not expand the selection to m.end(). I have tested the program, and m.start() and m.end() are of different values.
If anyone know what causes the problem, please tell me. I'll appreciate it.
Edit: Thank you for helping! I find an answer to the question. It has something to do with the pin which is used to move the cursor and select text (I don't know what it's called...). If it is shown in the textfield, and setSelection() is called, the EditText will not show the selection correctly. However, if you then use getSelectionStart() and getSelectionEnd(), you'll find they are exactly the same value of m.getStart() and m.getEnd(). This could be a bug. So my solution is to call clearFocus() first. The modified code is like this:
txt.clearFocus();
while (true) {
try {
m.find(start);
txt.setSelection(m.start(), m.end());
txt.requestFocus();
break;
} catch (IllegalStateException ex) {
if (start == 0) {
err_notfound.show();
break;
}
start = 0;
}
}
And it works.
I tested your code and put in one modiication.
Matcher m = Pattern.compile("1*", Pattern.CASE_INSENSITIVE).matcher(txt.getText());
I then made sure that my EditText had only 1's and it highlighted the entire thing.
You many need to confirm that your Regular Expressions are written correctly. You could see more on regualr expressions here(same site I just used).