androiddelphiin-app-subscription

How to get updated subscription status after cancellation without restarting the app (Google Play Billing in Delphi)?


I’m implementing subscription functionality in my mobile app using Google Play Billing and TInAppPurchase in Delphi. I’ve encountered an issue that I hope someone here might have already faced and solved.

When a user cancels a subscription, and the previously paid period fully expires, I expect that the app would stop recognizing the subscription as active. However, even after calling:

InAppPurchase.SetupInAppPurchase;
InAppPurchase.QueryProducts;

…the subscription still appears active in the app — InAppPurchase.IsProductPurchased(PlayMarketProductID) continues to return true.

But if I restart the app, the same method correctly returns false, and the subscription is no longer shown as active.

This leads me to believe that either the TInAppPurchase component or the underlying Google Billing client caches the subscription status, and that cache isn't invalidated until app restart.

Is there a way to force-refresh the current subscription state without restarting the app, after the subscription has been cancelled and fully expired?

I use Delphi 12.1.


Solution

  • I didn't look at the iOS implementation of TInAppPurchase, but for the Android implementation there is indeed a cache in the TInAppPurchase component itself. That cache is populated during component startup, and when receiving real-time updates from Google.

    Unfortunately, items are removed from that cache only when they are explicitly consumed by the app calling TInAppPurchase.ConsumeProduct(s). And subscriptions are non-consumable items in Google Play.

    When querying Google, or receiving real-time updates from Google, new purchases detected since the last query/update are added to the cache, but expired/cancelled items are not removed. If a subscription has fully expired, it is simply not reported as a purchased item anymore. But TInAppPurchase does not handle the case where an item is in the purchase list and then disappears from the list.

    That explains the behavior you are seeing. On startup, a subscription that has already fully expired is not in the purchase list and thus not added to the cache to begin with. But, if the subscription expires while the app is running, the subscription is not removed from the cache. I have reported this to Embarcadero for you:

    RSS-3516: TInAppPurchases does not remove expired subscription from Inventory

    Looking at Google's documentation, there is a whole Subscription Lifecycle that TInAppPurchases does not implement. It only focuses on the One-Time Purchase Lifecycle.

    In any case, if you don't want to restart your whole app, then you should be able to just destroy the TInAppPurchases component and re-create it so it starts over with a fresh state.