How can I parse a price from Google Play In-app billing

I use the following code to parse prices from Google Play In-App Billing:

private static Number parsePrice(String priceFromGoogle) { Locale currencyLocale = getCurrencyLocale(priceFromGoogle); NumberFormat numberFormat = NumberFormat.getCurrencyInstance(currencyLocale); Number number = null; try { number = numberFormat.parse(priceFromGoogle); } catch (ParseException e) { e.printStackTrace(); } return number; } private Locale getCurrencyLocale(String price) { Locale locale = null; for (Locale availableLocale : Locale.getAvailableLocales()) { NumberFormat numberFormat = NumberFormat.getCurrencyInstance(availableLocale); try { numberFormat.parse(price); locale = availableLocale; break; } catch (ParseException e) { //do nothing } } return locale; } 

It works great on my test devices and in my locale. But on some devices and in some countries I encounter such prices: "Php1,337,07", "US $ 29.99", "MX $ 374.79". In this case, my approach does not work.

Is there a universal approach to solving this problem?

+4
source share
3 answers

Check their billing sample project in the application and modify SkuDetails.java to get this information:

 import org.json.JSONException; import org.json.JSONObject; /** * Represents an in-app product listing details. */ public class SkuDetails { String mItemType; String mSku; String mType; int mPriceAmountMicros; String mPriceCurrencyCode; String mPrice; String mTitle; String mDescription; String mJson; public SkuDetails(String jsonSkuDetails) throws JSONException { this(IabHelper.ITEM_TYPE_INAPP, jsonSkuDetails); } public SkuDetails(String itemType, String jsonSkuDetails) throws JSONException { mItemType = itemType; mJson = jsonSkuDetails; JSONObject o = new JSONObject(mJson); mSku = o.optString("productId"); mType = o.optString("type"); mPrice = o.optString("price"); mPriceAmountMicros = o.optInt("price_amount_micros"); mPriceCurrencyCode = o.optString("price_currency_code"); mTitle = o.optString("title"); mDescription = o.optString("description"); } public String getSku() { return mSku; } public String getType() { return mType; } public String getPrice() { return mPrice; } public String getTitle() { return mTitle; } public String getDescription() { return mDescription; } public int getPriceAmountMicros() { return mPriceAmountMicros; } public String getPriceCurrencyCode() { return mPriceCurrencyCode; } @Override public String toString() { return "SkuDetails:" + mJson; } } 
+6
source

You can get the micron price in JSON received by IabHelper.

This is not officially documented, but here is how I did it by editing SkuDetails.java :

 public class SkuDetails { ... Double mPriceMicros; public SkuDetails(String itemType, String jsonSkuDetails) throws JSONException { ... String priceMicros = o.optString("price_amount_micros"); if (priceMicros != null) { String format = new StringBuilder(priceMicros).insert(priceMicros.length() - 6, ".").toString(); mPriceMicros = Double.parseDouble(format); } } ... public Double getPriceMicros() { return mPriceMicros; } } 

Hope this helps!

PS: I tried your price class, but he analyzed 0.8 for 0.89 €

+6
source

Since Google Play can return prices in a currency format that is not supported by java.text.NumberFormat, I wrote my own implementation

 public class Price { private double value; private String currency; private String pattern; private DecimalFormat decimalFormat; private Price() {} private static String currencyToDecimalFormat(String value, Price price) { char decimalSeparator = '.'; char groupingSeparator = 0; if (value.length() >= 3) { char[] chars = value.toCharArray(); if (chars[chars.length - 2] == ',') { decimalSeparator = ','; chars[chars.length - 2] = '.'; } else if (chars[chars.length - 3] == ',') { decimalSeparator = ','; chars[chars.length - 3] = '.'; } value = new String(chars); } if (value.contains(",")) { groupingSeparator = ','; value = value.replaceAll(",", ""); } else if (value.contains(" ")) { groupingSeparator = ' '; value = value.replaceAll(" ", ""); } else if (value.contains("\u00A0")) { groupingSeparator = '\u00A0'; value = value.replaceAll("\u00A0", ""); } DecimalFormatSymbols symbols = new DecimalFormatSymbols(); if (groupingSeparator != 0) { price.decimalFormat = new DecimalFormat("###,###.00"); symbols.setGroupingSeparator(groupingSeparator); } else { price.decimalFormat = new DecimalFormat("######.00"); } symbols.setDecimalSeparator(decimalSeparator); price.decimalFormat.setDecimalFormatSymbols(symbols); return value.replaceAll(",", ""); } public static Price parsePrice(String priceFromGoogle) { Price price = new Price(); StringBuilder patternBuilder = new StringBuilder(); Pattern pattern = Pattern.compile("(?:[0-9]{1,3})(?:[0-9,.\\s\u00A0]+)"); Matcher matcher = pattern.matcher(priceFromGoogle); matcher.find(); String priceString = matcher.group(); if (priceFromGoogle.indexOf(priceString) == 0) { if (priceFromGoogle.length() != priceString.length()) { price.currency = priceFromGoogle.substring(priceString.length()); } else { price.currency = ""; } } else { price.currency = priceFromGoogle.substring(0, priceFromGoogle.indexOf(priceString)); } price.currency = price.currency.trim(); if (priceFromGoogle.startsWith(price.currency)) { patternBuilder.append("%1s"); char nextChar = priceFromGoogle.charAt(price.currency.length()); if (nextChar == ' ' || nextChar == 0xA0) { patternBuilder.append(' '); } patternBuilder.append("%2$s"); } else { patternBuilder.append("%2$s"); char prevChar = priceFromGoogle.charAt(priceFromGoogle.indexOf(price.currency) - 1); if (prevChar == ' ' || prevChar == 0xA0) { patternBuilder.append(' '); } patternBuilder.append("%1s"); } price.pattern = patternBuilder.toString(); priceString = trim(priceString); priceString = currencyToDecimalFormat(priceString, price); price.value = Double.parseDouble(priceString); return price; } @Override public String toString() { if (pattern != null) { return String.format(pattern, currency, decimalFormat.format(value)); } else { return ""; } } 

}

EDIT1:

Because Google uses unused space instead of regular space, you need to check this and use the custom trim function:

 public static String trim(String text) { int start = 0, last = text.length() - 1; int end = last; while ((start <= end) && (text.charAt(start) <= ' ' || text.charAt(start) == 0xA0)) { start++; } while ((end >= start) && (text.charAt(end) <= ' ' || text.charAt(end) == 0xA0)) { end--; } if (start == 0 && end == last) { return text; } return text.substring(start, end); } 
+4
source

Source: https://habr.com/ru/post/1499914/


All Articles