Android - Fixing European Currency Input which Uses Commas instead of Decimals - android

Firstly, I know Doubles aren't the best for currency, but in this case, precision is not profoundly important. So, I have a live app in the Play store and I found a problem with Euro currencies. For some reason, if a Euro localization is used (can't reproduce this with ADB localizations) users can enter a comma in a numberDecimal EditText to delimit the dollars and cents. So, when you're expecting to get "1000.00" from a user in North America, you may get "1000,00" from someone in Norway.
This being said, is it typical that numberDecimal localizes like this and allows for the comma? If so, do you know if it limits users to inserting just the last comma? I am asking as I am using the following code to fix this problem, as you can see, it relies on their being just a single comma to replace:
// Required to handle European use of commas instead of decimals places
// in their currency.
edittext_amount.addTextChangedListener(new TextWatcher() {
public void afterTextChanged(Editable edittext_amount) {
String amount = "";
if (edittext_amount != null) {
try {
amount = edittext_amount.toString().replace(",", ".");
double_edittext_amount = Double.parseDouble(amount);
}
catch (NumberFormatException e) {
// Error
}
}
}
As mentioned, the above code was instituted to prevent the comma from creating an error, the error I receive is as follows:
java.lang.NumberFormatException: Invalid double: "1000,00"
at java.lang.StringToReal.invalidReal(StringToReal.java:63)
at java.lang.StringToReal.parseDouble(StringToReal.java:269)
at java.lang.Double.parseDouble(Double.java:295)
at java.lang.Double.valueOf(Double.java:332)
at com.ootpapps.saving.made.simple.SavingsPlanEditor.validateSavingsPlan(SavingsPlanEditor.java:233)
at com.ootpapps.saving.made.simple.SavingsPlanEditor.access$1(SavingsPlanEditor.java:217)
at com.ootpapps.saving.made.simple.SavingsPlanEditor$2.onClick(SavingsPlanEditor.java:109)
at android.view.View.performClick(View.java:3644)
at android.view.View$PerformClick.run(View.java:14313)
at android.os.Handler.handleCallback(Handler.java:605)
at android.os.Handler.dispatchMessage(Handler.java:92)
at android.os.Looper.loop(Looper.java:137)
at android.app.ActivityThread.main(ActivityThread.java:4517)
at java.lang.reflect.Method.invokeNative(Native Method)
at java.lang.reflect.Method.invoke(Method.java:511)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:993)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:760)
at dalvik.system.NativeStart.main(Native Method)
Thank you for your insight, I hope to settle this once and for all!
Edit - Changed the code to use NumberFormat, as follows:
// Required to handle European use of commas instead of decimals places
// in their currency.
edittext_amount.addTextChangedListener(new TextWatcher() {
public void afterTextChanged(Editable edittext_amount) {
String amount = "";
if (edittext_amount != null) {
try {
amount = edittext_amount.toString();
NumberFormat number_format = NumberFormat.getNumberInstance();
double_edittext_amount = number_format.parse(amount).doubleValue();
}
catch (NumberFormatException e) {
// Error
}
catch (ParseException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}

This is an alternative way to do what you are doing;
String amount = null;
String fist = null;
String second = null;
if (edittext != null){
amount = edittext.to string();
if (amount.contains(","){
StringTokenizer tokens = new StringTokenizer(CurrentString, ",");
first = tokens.nextToken();// this will contain the whole number
second = tokens.nextToken();//this will contain the decimal part
} else if (amount.contains("."){
StringTokenizer tokens = new StringTokenizer(CurrentString, ".");
first = tokens.nextToken();// this will contain the whole number
second = tokens.nextToken();//this will contain the decimal part
}//That bit removed the decimal points, from the strings, now we just put them back together
String fullNumber = first + "." + second;
double_edittext_amount = Double.parseDouble(fullNumber);
Hope this helps

Related

NumberFormat removing comma ( , ) from value?

I have this little crazy method that removes decimal places from string value.
private double getDoubleFromString(final String value) throws ParseException {
NumberFormat format = NumberFormat.getInstance(Locale.getDefault());
Number number = format.parse(value);
return number.doubleValue();
}
It produces values with out comma ( , ) if local language is 'en' it working fine, in other languages that contains , in that strings it's returns value without comma.
Ex :
xx,x
result is xxx.
74,5 --> 745 (problem facing in this format)
74.5 --> 74.5 (working fine it string has dot)
I do need the separator to be a dot or a point and a comma along with value string. Does anybody have a clue of how to accomplish this little feat?
Try this
private double getDoubleFromString(final String value) throws ParseException {
String newvalue= value.replace(",",".");
NumberFormat format = NumberFormat.getInstance(Locale.getDefault());
Number number = format.parse(newvalue);
return number.doubleValue();
}
SAMPLE CODE
try {
Log.e("RESULT_DATA",getDoubleFromString("88,5")+"");
Log.e("RESULT_DATA",getDoubleFromString("79.5")+"");
} catch (ParseException e) {
e.printStackTrace();
}
OUTPUT
03-22 18:37:09.173 7103-7103/? E/RESULT_DATA: 88.5
03-22 18:37:09.174 7103-7103/? E/RESULT_DATA: 79.5

Android app crashes when no value is in edit text

I am making a unit converter, but if I do not enter any value into edit text and press the calculate button the app crashes with error Invalid float: "". Also, I want to forbid zeroes from being entered before numbers (eg. 0300). How do I accomplish this?
//handle calculate
calcButton=(Button)findViewById(R.id.calcButton);
calcButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
Spinner spinner = (Spinner) findViewById(R.id.unit_spinner);
String spinnerText = spinner.getSelectedItem().toString();
EditText unit_edit = (EditText) findViewById(R.id.unit_edit);
amount = Float.valueOf(unit_edit.getText().toString());
if (unit_edit.getText().toString().equals(null)) {
Toast.makeText(getApplicationContext(), "Insert Value To Convert",
Toast.LENGTH_LONG).show();
} else {
switch (spinnerText) {
case "Kilograms":
kilograms = amount;
grams = amount * 1000;
ListView();
break;
case "Grams":
grams = amount;
kilograms = amount / 1000;
ListView();
break;
}
}
}
});
}
You are probably getting an NumberFormatException thrown since the EditText fields text is "" and "" is not a valid float value, the exception is thrown at the following line:
amount = Float.valueOf(unit_edit.getText().toString());
What you'll need to do is add some validation and checking before trying to get the float value of a String.
Check the methods documentation for more details http://docs.oracle.com/javase/7/docs/api/java/lang/Double.html#valueOf(java.lang.String)
This might be useful for your EditText to limit input to numbers only.
<EditText
android:id="#+id/unit_edit"
android:inputType="number"
/>
You can also limit the digits, type of number such as decimal
<EditText
android:id="#+id/unit_edit"
android:digits="0123456789."
android:inputType="numberDecimal"
/>
You can't parse an empty value to float. You should first test if it's empty, and then do what you want, something like this:
String text = unit_edit.getText().toString();
if(!text.isEmpty()){ // Test if the text is empty
if(text.matches("[0-9]+")){ // Test if it only contains numbers, using REGEX
amount = Float.valueOf(text); // Only then parse to float.
// Switch and rest of the stuff
} else {
Toast.makeText(getApplicationContext(), "Use only numbers from 0 to 9.",
Toast.LENGTH_LONG).show();
}
} else {
Toast.makeText(getApplicationContext(), "The field is empty",
Toast.LENGTH_LONG).show();
}
The comments explain what's going on. About the leading 0 in some numbers, using "valueOf" will remove it already, and 0300 will be parsed as 300, so there's nothing to worry about.If you still want something related to it, let me know and i'll edit my answer.

Getting Int from EditText causes error?

So first of all sorry if this has already been asked and answered before, I couldn't find anything relating to my issue.
So I'm working on a project for college and I need to get int values from EditText widgets. I was told to use parseInt to do this however when running my program, that line of code causes the application to crash. I don't know what I'm doing wrong, I'm still very new to android development, thanks for the help :)
public void Calculate (View view)
{
int MilesTravelled;
int FuelUsed;
int MPG;
/* the two lines below are what cause the application to crash */
MilesTravelled = Integer.parseInt(txtMilesTravelled.getText().toString());
FuelUsed = Integer.parseInt(txtFuelUsed.getText().toString());
FuelUsed = (int) (FuelUsed / 4.55);
MPG = MilesTravelled / FuelUsed;
lblMPG.setText(FuelUsed);
}
Do you have this in the onCreate() function?
EditText txtMilesTravelled = (EditText) findViewById(R.id.YourEditText);
But I think you mixed Integer and int. They are not the same:
See this link!
First of all, don't capitalize the first letter of an variables or method names. Following the Java coding conventions, only do that for classes.
What is probably causing your app to crash is you trying to set the text of a label to an integer. The setText method for a TextView needs to take in a string.
So change:
lblMPG.setText(FuelUsed);
to:
lblMPG.setText(String.valueOf(FuelUsed));
Otherwise it might be that it's trying to parse a non-numerical string to an integer.
For exmaple, if the EditText is blank, it will cause your app to crash. To prevent that, try this:
int MilesTravelled = 0, FuelUsed = 0;
try {
MilesTravelled = Integer.parseInt(txtMilesTravelled.getText().toString());
FuelUsed = Integer.parseInt(txtFuelUsed.getText().toString());
} catch (NumberFormatException nfe) {
Toast.makeText(getApplicationContext(), "Error NFE!", 0).show();
nfe.printStackTrace();
}
This way, it will catch a NumberFormatException error (parsing a string to an integer that can't be represented as an integer, such as "hello"). If it catches the error, it will toast that an error has occurred and your integer variables will remain 0.
Or you could just test if the strings contain only digits using the following regex:
int MilesTravelled = 0, FuelUsed = 0;
if (txtMilesTravelled.getText().toString().matches("[0-9]+")) {
MilesTravelled = Integer.parseInt(txtMilesTravelled.getText().toString());
} else {
// contains characters that are not digits
}
if (txtFuelUsed.getText().toString().matches("[0-9]+")) {
FuelUsed = Integer.parseInt(txtFuelUsed.getText().toString());
} else {
// contains characters that are not digits
}
If that's not the problem, then make sure you define your variables properly.
txtMilesTravelled and txtFuelUsed should be EditText:
EditText txtMilesTravelled = (EditText)findViewById(R.id.txtMilesTravelled);
EditText txtFuelUsed = (EditText)findViewById(R.id.txtFuelUsed);
And make sure that your R.id.editText actually exists on your layout and that the IDs are the correct ones.
Last thing, make sure FuelUsed is not 0 before calculating MPG because then you are dividing by 0:
int MPG = 0;
if (FuelUsed != 0) {
MPG = MilesTravelled / FuelUsed;
}
I am assuming that you're entering perfect integers in the EditTexts. It might be a good idea to use the trim function txtMilesTravelled.getText().toString().trim() before using parseInt.
However, I think the major problem is here : lblMPG.setText(FuelUsed);
FuelUsed is an integral value, when you pass an integer to setText(), it looks for a string resource with that integral value. So you should be passing a String to the setText() method.
Use : lblMPG.setText(Integer.toString(FuelUsed));

Compare R.id to int

I am building an simple Android app am looking for a way to compare number input to a pre-stored integer. My first though was:
if(R.id.number == 123456){
}
This comparison does not work. I have also tried .equals, with no avail. Does anyone have any thoughts on how to compare the two values?
The R.id.number refers to a View's id (most likely an EditText since you say you are comparing user input). Thus, comparing that to a number would definitely not be what you're looking for. Find the EditText via findViewById(), parse its text into an integer and compare that.
Eg
public void onCreate (Bundle b){
super.onCreate (b);
EditText e = (EditText) findViewById (R.id.number);
int num = 0;
try{
num = Integer.parseInt (e.getText().toString().trim());
}
catch (NumberFormatException e){
}
if (num == 123456){
System.out.println ("Input equal");
}
}

User's language dependent float representation

I am fighting with making my app language dependent. The user needs to enter a float. I am using a EditText to display the current value and allow editing.
To prepare I coded:
st = String.format("%.2f", myFloat);
edTxt = (EditText) findViewById(R.id.myEditText);
edTxt.setText(st, TextView.BufferType.EDITABLE);
edTxt.selectAll();
Now the user is presented the value. If in Settings of my device, I set my language to Deutsch (German) an float value of 2.80 is displayed as 2,80. On onPause of the activity I retrieve the value and convert it from string to float - and get a NumberFormatException error because of the comma.
Should be easy I thought, I just need to replace the comma by a dot, and coded:
String st ="";
st = edTxt.getText().toString();
st.replace(",", ".");
try{
float minV = Float.valueOf(st);
} catch (NumberFormatException nfe){
mShowAToast("NumberFormatException: " + st);
}
And surprise: The app runs into the catch and the toast shows st as "2,80" instead of "2.80", st.replace didn't do its job.
(probably it did, but)
Do I oversee anything?
If you have an float value that use ',' as decimal separator. You can parse it using a Locale class. Check the following code.
public static void main(String[] args) {
try {
// Number and NumberFormat are in java.text.*;
Number numberG = NumberFormat.getNumberInstance(java.util.Locale.GERMAN).parse("-1.234,56");
if (numberG instanceof Double) {
System.out.println(">" + numberG.doubleValue());
}
} catch (ParseException e) {
e.printStackTrace();
}
}
It will print:
>-1234.56
So instead of use java.util.Locale.GERMAN you can use the defaul locale: java.util.Locale.getDefault() of your JVM.
About the replace function of String I have compared the specfication of Android API and Oracle JDK and both are the same. So I think it must return what you expected. Just in case I have tried the folowing in my JDK:
String value = "-1.234,56";
System.out.println(value.replace(',', '.'));
System.out.println(value.replace(",", "."));
And both are printing: -1.234.56

Categories

Resources