Android - Invalid Double "#,##" - java

A user of my app is having a error and the app is crashing
I've looked at the report and it's stating
Caused by: java.lang.NumberFormatException: Invalid double: "1,36"
I have reproduced the data inputted on my app and I don't have the issue at all
I have even asked her to send me her database so i can import the exact data and it still worked okay for me
I'm confused as to where the double is getting formatted like that as I can't see anywhere in my code where it would get formatted with a ,
Any suggestions as to what's going on?

Simple way is (do it above your parce):
if (str.contains(",")) {
str.replace(",",".");
}

I just have faced the same problem. I was converting float value to String. Yes, it must be a locale issue. As said in one of the comments, Some locales use , as a decimal separator.
Initially I was converting float like-
String.format("%.1f", value);
Then I changed the code to
String.format(Locale.ENGLISH, "%.1f", value);
So, forcing the string to be converted with English local worked for me.

You seem to have encountered a locale problem. Different locales have . and , as fractional part separator. You can use java.text.NumberFormat to work with the locale you want, e.g. FRANCE for comma and US for point:
// somewhere at Utils.java:
public static final NumberFormat DOUBLE_FORMAT = NumberFormat.getInstance(Locale.FRANCE);
// at call site:
double d = Utils.DOUBLE_FORMAT.parse("1,234").doubleValue();

Related

Changing android number locale

I successfully added multiple locales to my app and figured out how to switch between them, but the problem is after I switch the locale everything works all right except numbers
For example if I switch to Persian numbers will remain 123 which is wrong and should be switched to ١٢٣.
I can't use String.format(number) cause most of my numbers are included in Strings. Anyone can help me out here?
if you want to translate number as well you must not bind it as a string , you must set it as float or int
<string name="numberRes">%d</string>
textview.setText(String.format(R.string.numberRes,numberValue))
numberValue must be an integer in case of float replace %d with %f
in case all numbers in string format use
textview.setText(String.format(R.string.numberRes,Integer.valueOf(numberValue)))
and be careful of NumberFormatException if your string has a wrong number format
Best solution I found is a hacky way to force a numeral font in Persian/Arabic locales!
You have to create multiple font.xml files and put them in res/font then use locale based themes to assign related font to android:fontFamily.
Here is the result:
font/font-en.xml
font/font-ar.xml
font/font-fa.xml
values-en/themes.xml
values-ar/themes.xml
values-fa/themes.xml

Android studio strange warning

I'm new to code in Android Studio and when i set a integer in a text like this:
textview.setText(String.format("%d",1));
This code give me back a warning:
Implicitly using the default locale is a common source of bugs: Use String.format (Locale,...)
What is the correct code for put an integer in a .setText?
I founded more question on stackoverflow but don't apply to this.
What is the correct code for put an integer in a .setText?
You simply need to convert your int as a String, you can use Integer.toString(int) for this purpose.
Your code should then be:
textview.setText(Integer.toString(myInt));
If you want to set a fixed value simply use the corresponding String literal.
So here your code could simply be:
textview.setText("1");
You get this warning because String.format(String format, Object... args) will use the default locale for your instance of the Java Virtual Machine which could cause behavior change according to the chosen format since you could end up with a format locale dependent.
For example if you simply add a comma in your format to include the grouping characters, the result is now locale dependent as you can see in this example:
System.out.println(String.format(Locale.FRANCE, "10000 for FR is %,d", 10_000));
System.out.println(String.format(Locale.US, "10000 for US is %,d", 10_000));
Output:
10000 for FR is 10 000
10000 for US is 10,000

icu4j returns currency code instead of symbol

Background
I have an Android application where I want to format an integer value as a currency string depending on the ISO code and current locale. I'm using ICU library 1.8.1 for that.
For example, if I have a value 75 and the ISO code is "USD", I want to see "$75" on US locale, but "USD75" on French locale.
Problem
The problem is that I always see "USD75" even when I explicitly set the locale to US. I thought the problem is in my NumberFormat currency instance, but then I tried to simply get the currency symbol and noticed that it's incorrect. For some reason getSymbol() method always returns currency code.
public void test() {
Locale.setDefault(Locale.US);
String theISOCode = "USD"
Currency currency = Currency.getInstance(theISOCode);
currency.getCurrencyCode(); // "USD". This works as expected
currency.getSymbol(); // "USD". This looks weird.. Shouldn't it be "$"?
currency.getSymbol(Locale.US); // "USD". Same here, I expect it to be "$"
currency.getSymbol(ULocale.US); // still "USD"
}
I also checked this link: Java: Currency symbol based on ISO 4217 currency cod. It seems my app works a bit differently. Not sure if it's a bug in the library.
Question
It makes sense to me that currency.getSymbol() returns "USD" if your locale is Locale.FRANCE. But why does it return "USD" when my locale is Locale.US? Would be great if I could find a solution without switching the library.
The issue turned out to be a bug in the library. After updating the version the issue got resolved. Thanks #Omid for looking into this.

NumberFormatException on European Versions of Android?

I have an app which runs the following two lines of code upon starting:
DecimalFormat decim = new DecimalFormat("#.00");
return Double.parseDouble(decim.format(totalNumberOfCredits));
When I start the app on my American phone, the value of decim.format(totalNumberOfCredits) is .00.
However, in my Google Play Developer Console, I have a dozen crashes, all of which look like this:
Caused by: java.lang.NumberFormatException: Invalid double: ",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)
Is it really possible that DecimalFormat is producing a comma version of the decimal on European phones?
Is it really possible that DecimalFormat is producing a comma version of the decimal on European phones?
Yes, absolutely. That's what it's meant to do, after all:
Creates a DecimalFormat using the given pattern and the symbols for the default locale. This is a convenient way to obtain a DecimalFormat when internationalization is not the main concern.
To obtain standard formats for a given locale, use the factory methods on NumberFormat such as getNumberInstance. These factories will return the most appropriate sub-class of NumberFormat for a given locale.
Note that this isn't a matter of a "European version of Android" - it's just a matter of using Android in a context where the default locale uses , as the decimal separator.
If you want to use the symbols for a particular locale, but using a specific pattern, you could use:
DecimalFormatSymbols symbols = DecimalFormatSymbols.getInstance(Locale.US);
DecimalFormat format = new DecimalFormat("#.00", symbols);
Having said that, it's not at all clear what you're trying to do in the first place - why would you format and then parse a number? You should almost always avoid string conversions when you don't really need them. Why not just convert it directly? (We don't know what totalNumberOfCredits is, which doesn't help.)
public double getTwoPointDecimal(double value) {
DecimalFormatSymbols symbols = new DecimalFormatSymbols(Locale.US);
return Double.parseDouble(new DecimalFormat("##.##", symbols).format(value));
}
try it, its help me in my project
double unit = Float.parseFloat(String);
DecimalFormat decimal = new DecimalFormat("##.###").format(unit);
try this it help me in my project

Understanding the strange output of java.util.Locale

I had a perception that Locale is just about adding comma at proper positions at least in case of numbers. But I see a different output for what I have tried.
I tried the following,
public static void main(String[] args) {
DecimalFormat df = null;
df = (DecimalFormat) DecimalFormat.getInstance(Locale.CHINESE);
System.out.println("Locale.CHINESE "+df.format(12345.45));
df = (DecimalFormat) DecimalFormat.getInstance(Locale.GERMAN);
System.out.println("Locale.GERMAN "+df.format(12345.45));
}
Output:
Locale.CHINESE 12,345.45
Locale.GERMAN 12.345,45
If you carefully look at the comma's, you'll see a major difference.
Now, the javadoc for java.util.Locale says
... An operation that requires a Locale to perform its task is called locale-sensitive and uses the Locale to
tailor information for the user. For example, displaying a number is a locale-sensitive operation--the number
should be formatted according to
the customs/conventions of the user's native country, region, or culture ...
I see a comma being interpreted as decimal point in another Locale, which is really a curious thing, as the value is being changed.
So, help me understand this. What exactly is Locale? Won't the drastic change in output cause major issue in code/data?
I had a perception that Locale is just about adding comma at proper positions at least in case of numbers.
No, it affects the symbols used as well, as you've seen.
So, help me understand this. What exactly is Locale? Won't the drastic change in output cause major issue in code/data?
Only if you don't use them correctly :) Machine-to-machine communication should usually not be localized; typically if you really need to use text, it's best to use US as a reasonably invariant locale.
See DecimalFormatSymbols for more details of what is locale-specific.
I see nothing wrong with the above. The German way of representing 12345.45 is 12.345,45
and the Chinese way of representing the same number is 12,345.45 .
So, help me understand this. What exactly is Locale? Won't the drastic
change in output cause major issue in code/data?
No it won't you just need to keep track of the locale of the input and how you want it formatted.

Categories

Resources