Как я могу разобрать цену из биллинга Google Play In-app

Я использую следующий код для разбора цены в 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; } 

Он отлично работает на моих тестовых устройствах и в моей локали. Но на некоторых устройствах и в некоторых странах я сталкиваюсь с такими ценами: «Php1,337,07», «US $ 29.99», «MX $ 374,79». В этом случае мой подход не работает.

Существует ли универсальный подход к решению этой проблемы?

Проверьте их проект образца биллинга в приложении и измените SkuDetails.java, чтобы получить эту информацию:

 import org.json.JSONException; import org.json.JSONObject; /** * Represents an in-app product's 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; } } 

Вы можете получить цену в микрофонах в JSON, полученном IabHelper.

Это официально не документировано, но вот как я это сделал, отредактировав 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; } } 

Надеюсь это поможет !

PS: Я пробовал ваш ценовой класс, но он проанализировал 0,8 за 0,89 €

Поскольку Google Play может возвращать цены в формате валюты, который не поддерживается java.text.NumberFormat, я написал свою собственную реализацию

 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:

Из-за того, что Google использует неиспользуемое пространство вместо обычного пространства, вам нужно проверить это и использовать пользовательскую функцию обрезки:

 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); }