I'm calling Google Maps Intent from my activity with this code found on StackOverflow:
final String uriContent = String.format(Locale.ENGLISH, "http://maps.google.com/maps?q=loc:%s", pCoordinate);
final Intent intent = new Intent(Intent.ACTION_VIEW, Uri.parse(uriContent));
pContext.startActivity(intent);
where pCooriante contains entirely address such as 1.23456,7.8901.
It works well when my phone is using English as its language, but when I change it to French or Vietnamese (which use comma , as its number decimal seperator), it can't work anymore, because the query proceeded by Google Maps look like: 1,000,2,000 (it is shown in the search bar, and after that, a message like Cannot find 1,0000,2,0000 appears), although the exact URI I sent to the intent is 1.000,2.000 (the coordinate is converted to String to prevent Locale problems, and therefore the Locale.ENGLISH in String.format is more or less just abundant).
In short, Uri.parse(uriContent) return exactly the request with the query is 1.000,2.000, but Google Maps itself changed it. However, the code for direction works well with either Locale:
final String uriContent = String.format(Locale.ENGLISH, "google.navigation:q=%s", pCoordinate);
final Intent intent = new Intent(Intent.ACTION_VIEW, Uri.parse(uriContent));
pContext.startActivity(intent);
Is there anyway to prevent the conversion of Google Maps? If I use geo:<coordinate>, it's fine, but I need a marker at that position.
Addional information:
This code final String uriContent = String.format("geo:0,0?q=%s&z=19", pCoordinate); doesn't work too, the periods are converted into commas.
This code final String uriContent = String.format("geo:%s?q=%s&z=19", pCoordinate, pCoordinate); can bring the map center to the coordinate, but still cannot put the marker there, and with the error "Cannot find 'coordinate with periods replaced by commas'"
I am using a temporary solution to this problem, by converting the decimal form of coordinates to degree one. (For example, instead of sending 10.768717,106.651488, I send 10° 46' 7.3812",106° 39' 5.3568"). The conversion is just simple mathematics operation.
However, there was a problem with Java float and double precision, and that was a lot of distance when sending to Google Maps. Therefore I change my input data, convert data using C#'s decimal and my Android app just use it without manupilating anything. Here is the convesion (C#) code:
protected String convertDecimalToDegree(decimal pDecimal)
{
int degree = (int)Math.Floor(pDecimal);
pDecimal -= degree;
pDecimal *= 60;
int minute = (int)Math.Floor(pDecimal);
pDecimal -= minute;
pDecimal *= 60;
return degree + "° " + minute + "\' " + pDecimal + "\"";
}
Usage:
String[] coordinates = shop.MapCoordination.Split(',');
decimal n1 = Decimal.Parse(coordinates[0]);
decimal n2 = Decimal.Parse(coordinates[1]);
shop.MapCoordination = this.convertDecimalToDegree(n1) + "," + this.convertDecimalToDegree(n2);
I will mark this as answer for now, but I appreciate any solution without having to convert to this form.
You can use the following snippet to solve the problem
public String getCoordinates(String coordinates){
if(Locale.FRANCE == Locale.getDefault()){
Pattern p = Pattern.compile(",.*?(,)");
Matcher m = p.matcher(coordinates);
if (m.find( )) {
int index = m.end(); //gets the second comma position
String str1 = coordinates.substring(0,index-1);
String str2 = coordinates.substring(index,coordinates.length());
NumberFormat nf = NumberFormat.getInstance(Locale.FRANCE);
try {
str1 = nf.parse(str1).toString();
str2 = nf.parse(str2).toString();
} catch (ParseException e) {
e.printStackTrace();
}
return str1+","+str2;
}
}
return coordinates;
}
Updating the Google Maps app to the latest version (7.2.0) seems to fix the issue.
in Xamarin.Android:
using System.Globalization;
Android.Net.Uri.Parse("http://maps.google.com/maps?daddr=" + myLatitude.ToString(CultureInfo.InvariantCulture) + "," + myLongitude.ToString(CultureInfo.InvariantCulture)));
Related
I'm working on an app and facing an issue. I've tried a number of solutions but nothing solved my problem.
I need to round off two digits after decimal point.
For Example.
9.225 should be rounded off to 9.23
Thank you.
For Kotlin use "%.2f".format(number), for Java use String.format("%.2f", number)
Result:
You can use String.format("%.2f", d), this will rounded automatically. d is your value.
OR
You can use this
double d = 1.234567;
DecimalFormat df = new DecimalFormat("#.##");
Log.d(df.format(d));
You can get as a float value as well like below.
float value = Float.valueOf(df.format(d)); // Output will be 1.24
I would have gone with a probable over the top solution however this is what i came up with.
It uses regex to split the string value of the number passed and then rounds up/down depending on the leading digit after the decimal place. It will return a Double in the instance but you can change that if you like. It does throw IllegalArgumentException, but thats taste dependant.
/**
* #param value the value that is being transformed
* #param decimalPlace the decimal place you want to return to
* #return transformed value to the decimal place
* #throws IllegalArgumentException
*/
Double roundNumber(#NonNull Double value, #NonNull Integer decimalPlace) throws IllegalArgumentException {
String valueString = value.toString();
if(valueString.length()> decimalPlace+1){
throw new IllegalArgumentException(String.format("The string value of %s is not long enough to have %dplaces", valueString, decimalPlace));
}
Pattern pattern = Pattern.compile("(\\d)('.')(\\d)");
Matcher matcher = pattern.matcher(valueString);
if (matcher.groupCount() != 4) { //0 = entire pattern, so 4 should be the total ?
throw new IllegalArgumentException(String.format("The string value of %s does not contain three groups.", valueString));
}
String decimal = matcher.group(3);
int place = decimal.charAt(decimalPlace);
int afterDecimalPlace = decimal.charAt(decimalPlace + 1);
String newDecimal = decimal.substring(0, decimalPlace - 1);
newDecimal += afterDecimalPlace > 5 ? (place + 1) : place;
return Double.parseDouble(matcher.group(1) + "." + newDecimal);
}
I'm developing an app where I use the Geocoder to get a place's coordinates.
The operative is this:
The user defines an address.
The geocoder finds that address and I get the coordinates from that address.
This coordinates are in decimal format and I need them in degrees-minutos so I format them.
To format the coordinates from decimal to degrees-minutes I use:
String frmtLatitude = Location.convert(Double.parseDouble(lat), Location.FORMAT_MINUTES);
So, if I have for example this latitude 43.249591 in decimal value, it returns it like this 43:14.97546.
After this, I have to make some operations to finally get the latitude with this appearance: 4314.975
When I do this operations, one of them is to split the value using the ".". I split 14.97546 to get in one hand the 14 and in the other 97546.
Until here, everything ok. It works fine when I have my phone's language selected to be in english. But if I select to be in spanish, the app crashes. I have followed the stacktrace and it points there. Is like that in english when using the first commented function to convert from decimal to degrees-minutes it separates the decimals with a "." but if I have it in spanish, it separates them with a ",".
Can this really happen or the cause could be another thing?
We can look at the source code of the convert method
public static String convert(double coordinate, int outputType) {
if (coordinate < -180.0 || coordinate > 180.0 ||
Double.isNaN(coordinate)) {
throw new IllegalArgumentException("coordinate=" + coordinate);
}
if ((outputType != FORMAT_DEGREES) &&
(outputType != FORMAT_MINUTES) &&
(outputType != FORMAT_SECONDS)) {
throw new IllegalArgumentException("outputType=" + outputType);
}
StringBuilder sb = new StringBuilder();
// Handle negative values
if (coordinate < 0) {
sb.append('-');
coordinate = -coordinate;
}
DecimalFormat df = new DecimalFormat("###.#####");
if (outputType == FORMAT_MINUTES || outputType == FORMAT_SECONDS) {
int degrees = (int) Math.floor(coordinate);
sb.append(degrees);
sb.append(':');
coordinate -= degrees;
coordinate *= 60.0;
if (outputType == FORMAT_SECONDS) {
int minutes = (int) Math.floor(coordinate);
sb.append(minutes);
sb.append(':');
coordinate -= minutes;
coordinate *= 60.0;
}
}
sb.append(df.format(coordinate));
return sb.toString();
}
We can see that it uses a DecimalFormat with a given pattern. So, if we look to the DecimalFormat constructor :
public DecimalFormat(String pattern) {
// Always applyPattern after the symbols are set
this.symbols = new DecimalFormatSymbols(Locale.getDefault());
applyPattern(pattern, false);
}
We can see here that even if we give a pattern, it uses the locale values. The javadoc also said :
Parameters:
pattern A non-localized pattern string.
To finish, we can go here to see the different local variant of numbers representation : http://docs.oracle.com/cd/E19455-01/806-0169/overview-9/index.html
So we can see that US-English use the "dot format" and that Spanish use "comma format".
To answer your question : the proflem you're facing is probably due to the Decimal format of your locale. I advice you to be REALLY CAREFUL when converting types of objects to make manipulation on them. Converting an int to a String should be only to display it.
I think you should seperate decimal part of your number when it stills a float (or any decimal type) and then convert your object to a String to display it. You can take a look at Math class or search SO to get some example on how to this ;)
Also, as #Dmitry said, you can get DecimalSeparator with DecimalFormatSymbols.getDecimalSeparator().
Sources
Location.convert(double,int) source code
DecimalFormat(String) source code
Java "Decimal and thousands separators"
You are right, decimal seperator depends on your locale. You can get it by something like this
DecimalFormat df = new DecimalFormat();
DecimalFormatSymbols formatSymbols = df.getDecimalFormatSymbols();
char separator = formatSymbols.getDecimalSeparator();
I have double amount. Let amount to be 500000.12. I want to set value of the amount to TextView like this format 500,000.12 (where 12 is cents , 500,000 is dollars).
I wrote this function and it works
private String getAmountAsString(double amount) {
double integralPart = amount % 1;
int fractionalPart = (int) (amount - integralPart);
int integral = (int) integralPart * 100;
String strFractional = String.format("%,d", fractionalPart);
String strAmount = (strFractional + "." + String.valueOf(integral));
return strAmount;
}
But I think that there can be some easy and good way of doing this with java native functions. Can anybody help to find functions or some better way?
various Locale can be used to format float, double etc. You can use:
String.format(Locale.<Your Locale>, "%1$,.2f", myDouble);
Here .2f represents how many digits you want after decimal. If you are not specifying any locale it will use the default locale.
In String class this method is overloaded as:
format(String format, Object... args)
&
format(Locale l, String format, Object... args)
For more info have a look: Link1 , Link2 and Link3
Therefore NumberFormats are used. They are good to handle local differents for different countries.
//define a local, gets automated if a point or comma is correct in this Country.
NumberFormat anotherFormat = NumberFormat.getNumberInstance(Locale.US);
DecimalFormat anotherDFormat = (DecimalFormat) anotherFormat;
anotherDFormat.applyPattern("#.00");//set the number of digits afer the point
anotherDFormat.setGroupingUsed(true);// set grouping
anotherDFormat.setGroupingSize(3);//and size of grouping
double myDouble = 123456.78;
String numberWithSeparators = anotherDFormat.format(myDouble);//convert it
I think you have to take a look at this one
http://docs.oracle.com/javase/tutorial/i18n/format/decimalFormat.html
Here is my simple code
#Override
public void onClick(View v) {
try {
double price = Double.parseDouble(ePrice.getText().toString());
double percent = Double.parseDouble(ePercent.getText().toString());
double priceValue = price * percent/100.0f;
double percentValue = price - priceValue;
moneyToGet.setText(String.valueOf(priceValue));
moneyToPay.setText(String.valueOf(percentValue));
moneyToGet.setText("" + priceValue);
moneyToPay.setText("" + percentValue);
// catch
} catch (NumberFormatException ex) {
// write a message to users
moneyToGet.setText("");
}
}
});
This is a simple code for Percentage Calculator.
What I want is to avoid the Scientific Notation in my Calculator cause I don't want to explain to user what is Scientific Notation.
For example if I want to calculate 100,000,000 and cut 50% of it, it Should give me 50,000,000 which is giving me 5.0E7 And in my case this doesn't make any sense to the user. And of course I know both results are correct.
Thanks in Advance.
Check answer here. You can write
moneyToGet.setText(String.format("%.0f", priceValue));
You can try this DecimalFormat
DecimalFormat decimalFormatter = new DecimalFormat("############");
number.setText(decimalFormatter.format(Double.parseDouble(result)));
I would suggest using BigDecimals instead of doubles. That way you will have a more precise control over your calculation precision. Also you can get a non-scientific String using BigDecimal.toPlainString().
DecimalFormat decimalFormatter = new DecimalFormat("##.############");
decimalFormatter.setMinimumFractionDigits(2);
decimalFormatter.setMaximumFractionDigits(15);
This option will help you ##.## suffix 0 before decimal, otherwise output will be .000
btc.setText(decimalFormatter.format(btcval));
use this for displaying content
Use NumberFormater like
NumberFormat myformatter = new DecimalFormat("########");
String result = myformatter.format(yourValue);
I have an app which has a section that needs to convert the temperature from Celsius to Fahrenheit, but for some reason on only a couple phone models (like the htc desire and Sony Ericsson X10) it crashes at this part, but I have no idea why. can anyone help?
double cel = x/10;
finalTFF = 9.0f/5.0f * cel + 32.0;
DecimalFormat twoDForm = new DecimalFormat("##.0");
double NfinalTFF = Double.valueOf(twoDForm.format(finalTFF));
return twoDForm.format(NfinalTFF);
Why so difficult?
As I see, you want to convert a double into a string, so:
public static String celsiusToFahrenheit(double celsius) throws Exception {
double result = ((celsius * 9) / 5) + 32;
return String.format("%.2f", result);
}
That should work :)
You are probably getting NumberFormatException when calling
double NfinalTFF = Double.valueOf(twoDForm.format(finalTFF));
Depending on the language settings on the phone decimal separator is "." or ",". When calling valueOf, only "." is accepted. Keenora is correct that the code can be simplyfied, but to avoid the crash in your code you can add a replace statement like so:
double NfinalTFF = Double.valueOf(twoDForm.format(finalTFF).replace(",", "."));