26

I have upgraded my Kotlin app to android-billing 5.0 from 4.0, and as such, SkuDetails is now deprecated so I am migrating to using ProductDetails using the migration instructions.

Previously I displayed the purchase price for in-app purchases to the user using SkuDetails.price, but I cannot find a similar method in ProductDetails.

In Google Play Billing Library 5.0, is there a non-deprecated way to retrieve the price for an in-app purchase or subscription?

Peter
  • 2,654
  • 2
  • 33
  • 44

3 Answers3

32

Based on the documentation you can call getOneTimePurchaseOfferDetails() on ProductDetails to return a ProductDetails.OneTimePurchaseOfferDetails object, which has a getFormattedPrice() method to return the price for in-app purchases.

For subscriptions you can call getSubscriptionOfferDetails() which returns a list of ProductDetails.SubscriptionOfferDetails objects, which have a getPricingPhases() method to return different pricing phases. The pricing phase objects have a getFormattedPrice() method to get the price from.

UPDATE

To better explain what this new approach allows, you can now create multiple "base plans" for a given subscription product. For example, you could create an "unlimited" product, then create an "unlimited-annual" plan for $50/year and an "unlimited-monthly" plan for $5/month.

The ProductDetails returned for a configuration like that would look like this - where you have a single productId with multiple payment rates/plans. If you add a promotion (e.g. discount for the first year) that shows up with a non-null offerId under an existing base plan ID.

{
  productId: "unlimited",

  subscriptionOfferDetails: 
  [
    {
      basePlanId: "unlimited-monthly",
      offerId: null,
      pricingPhases:
      [
        {formattedPrice: "$5", billingPeriod: P1M, recurrence: 1}
      ]
    },

    {
      basePlanId: "unlimited-annual",
      offerId: null,
      pricingPhases:
      [
        {formattedPrice: "$50", billingPeriod: P1Y, recurrence: 1}
      ]
    },

    {
      basePlanId: "unlimited-annual",
      offerId: "unlimited-annual-promotion",
      pricingPhases:
      [
        {formattedPrice: "$30", billingPeriod: P1Y, recurrence: 2}
        {formattedPrice: "$50", billingPeriod: P1Y, recurrence: 1}
      ]
    }
  ],
 
  oneTimePurchaseOfferDetails: null
}

There are also details from Google here about the new format.

Tyler V
  • 9,694
  • 3
  • 26
  • 52
  • 34
    ... why would they change a perfectly fine & simple method into something so unnecessarily complicated?? – Big_Chair May 14 '22 at 21:43
  • 1
    No idea... I need to do this migration myself still but am putting it off for now... – Tyler V May 14 '22 at 22:33
  • 1
    Read https://qonversion.io/blog/google-play-billing-library-5-0/ to see the idea behind the curtain – Mixaz Jun 30 '22 at 10:19
  • 2
    @Big_Chair, no kidding, the API in version 4 was already insanely complicated, and they decided to add a new layer of complexity. – Tenfour04 Oct 09 '22 at 19:18
9

In Kotlin you can call this on the product

subscriptionOfferDetails?.get(0)?.pricingPhases?.pricingPhaseList?.get(0)?.formattedPrice
MrCreed
  • 131
  • 1
  • 8
  • 9
    It works, But ... OMG I can't believe that's the thing we have to write just to get the price .... !!! ??? – ekashking Oct 16 '22 at 04:01
  • @ekashking it used to be easier, but I guess google didn't think so – MrCreed Oct 16 '22 at 17:11
  • 6
    This will fail when the subscription base plan has multiple offers. subscriptionOfferDetails?.get(0)? -> from what I can see, it is not guaranteed that the base plan is at position 0 – Alex Busuioc Dec 02 '22 at 12:33
  • 1
    If we look the documentation, I', afraid, this oneliner is the simplest way to handle this, if we have one product with one time period. With many product with many time periods it is even more complicated. – Reijo Korhonen Jan 22 '23 at 19:16
3

In java you can get the price as a string (complete with the appropriate currency sign) thusly:

product.get(i).getOneTimePurchaseOfferDetails().getFormattedPrice()

where product is a List<ProductDetails> from the onProductDetailsResponse listener

(I understand the question was for kotlin, but this is one of the first hits you find when search for this solution so a Java answer is worth including as well).

Al Ro
  • 466
  • 2
  • 11