SubscriptionManager crashes by InvalidProductTypeException in Android device.

I tried to use SubscriptionManager.
The following is the code.

Dictionary<string, string> introductory_info_dict = m_AppleExtensions.GetIntroductoryPriceDictionary();

foreach (var item in controller.products.all)
{
    if (item.availableToPurchase)
    {
        Debug.Log(string.Join(" - ",
                    new[]
                    {
                    item.metadata.localizedTitle,
                    item.transactionID,
                    item.receipt
                    }));
        if (item.receipt != null)
        {
            if (item.definition.type == ProductType.Subscription)
            {
                if (checkIfProductIsAvailableForSubscriptionManager(item.receipt)) {
                    string intro_json = (introductory_info_dict == null || !introductory_info_dict.ContainsKey(item.definition.storeSpecificId)) ? null : introductory_info_dict[item.definition.storeSpecificId];
                    subscriptionManager = new SubscriptionManager(item, intro_json);
                    SubscriptionInfo info = subscriptionManager.getSubscriptionInfo();
                    Debug.Log("product id is: " + info.getProductId());

I referred to IAPDemo.cs.
This code works fine in iOS device, but an exception is occurred in Android device.
Here is the exception.

I tried to use m_GooglePlayStoreExtensions.GetProductJSONDictionary() instead of m_AppleExtensions.GetIntroductoryPriceDictionary(), but it didn’t work neither.

Can I use SubscriptionManager in Android device?
If so, how should I fix my code?

Unity version is 2018.4.15f1.
IAP version is 1.23.1.

Could you please narrow down the line where the exception occurs? And it doesn’t look like you included the entire method.

Here is the entire function.
The exception occurs on the line 33, “SubscriptionInfo info = subscriptionManager.getSubscriptionInfo();”

public void OnInitialized(IStoreController controller, IExtensionProvider extensions)
{
    m_AppleExtensions = extensions.GetExtension<IAppleExtensions> ();
    m_AppleExtensions.RegisterPurchaseDeferredListener(OnDeferred);

    Debug.Log("OnInitialized: PASS");

    storeController = controller;
    storeExtensionProvider = extensions;

    m_GooglePlayStoreExtensions = extensions.GetExtension<IGooglePlayStoreExtensions>();

    Dictionary<string, string> introductory_info_dict = m_AppleExtensions.GetIntroductoryPriceDictionary();

    foreach (var item in controller.products.all)
    {
        if (item.availableToPurchase)
        {
            Debug.Log(string.Join(" - ",
                        new[]
                        {
                        item.metadata.localizedTitle,
                        item.transactionID,
                        item.receipt
                        }));
            if (item.receipt != null)
            {
                if (item.definition.type == ProductType.Subscription)
                {
                    if (checkIfProductIsAvailableForSubscriptionManager(item.receipt)) {
                        string intro_json = (introductory_info_dict == null || !introductory_info_dict.ContainsKey(item.definition.storeSpecificId)) ? null : introductory_info_dict[item.definition.storeSpecificId];
                        subscriptionManager = new SubscriptionManager(item, intro_json);
                        SubscriptionInfo info = subscriptionManager.getSubscriptionInfo();
                        Debug.Log("product id is: " + info.getProductId());
                        Debug.Log("purchase date is: " + info.getPurchaseDate());
                        Debug.Log("subscription next billing date is: " + info.getExpireDate());
                        Debug.Log("is subscribed? " + info.isSubscribed().ToString());
                        Debug.Log("is expired? " + info.isExpired().ToString());
                        Debug.Log("is cancelled? " + info.isCancelled());
                        Debug.Log("product is in free trial peroid? " + info.isFreeTrial());
                        Debug.Log("product is auto renewing? " + info.isAutoRenewing());
                        Debug.Log("subscription remaining valid time until next billing date is: " + info.getRemainingTime());
                        Debug.Log("is this product in introductory price period? " + info.isIntroductoryPricePeriod());
                        Debug.Log("the product introductory localized price is: " + info.getIntroductoryPrice());
                        Debug.Log("the product introductory price period is: " + info.getIntroductoryPricePeriod());
                        Debug.Log("the number of product introductory price period cycles is: " + info.getIntroductoryPricePeriodCycles());

                        if (Result.True == info.isSubscribed())
                        {
                            if (Result.True == info.isCancelled())
                            {
                                Debug.Log( "Subscription Canceled" );
                            }
                            else
                            {
                            }
                        }
                        else if (Result.True == info.isExpired())
                        {
                            Debug.Log( "Subscription Expired" );
                        }
                    }
                    else {
                        Debug.Log("This product is not available for SubscriptionManager class, only products that are purchase by 1.19+ SDK can use this class.");
                    }
                }
                else
                {
                    Debug.Log("the product is not a subscription product");
                }
            }
            else
            {
                Debug.Log("the product should have a valid receipt");
            }
        }
    }
}

Thanks for the additional information, we have confirmed and the fix should be included in the next release, hopefully in a few weeks.

1 Like

Thank you!
I’m looking forward to the next release.

We’re still getting this error on V2.0.6 on Unity 2019.1.10f1. Is there an update yet? If not, is there a work around for Android subscriptions?

I will ask the team about its latest status.

Do you have an update about this? The fix was said to be complete 2 months ago.

Thanks, @SamOYUnity3D but this is VERY critical as its technically broken for all subscriptions on Android. Is there a work-around or a repo that we can use until release?

I suggest you update to the latest IAP version, and use the following code to avoid the app crash.

        try
        {
            SubscriptionManager p = new SubscriptionManager(item, intro_json);
            SubscriptionInfo info = p.getSubscriptionInfo();
        }
        catch (Exception ex)
        {
            Debug.Log(ex);
        }

Thanks @SamOYUnity3D . We’re already doing that but it just avoids the crash. We have no info about the subscription status so we have to auto-assume that it’s still active if it fails to parse.

Is the plugin being deprecated? aka, we should find alternative ways of fixing this?

1 Like

We have addressed this issue before and it has been fixed in IAP 1.22.1 and later. Since you mentioned that you still encounter this issue in the latest IAP version, I think we need further investigation. I would appreciate it if you can provide steps to reproduce.

OK sure. Let’s start by making sure we have the correct versions.

The Package manager says Version 2.0.6 which is the latest version available. The Changelog.md says [1.23.1] - 2019-11-18. If the bug has been resolved at the end of January, do we have that fix or not?

I see. I think this is a new issue. We couldn’t reproduce this issue in the latest version, it will be helpful if you can provide it. Also, could you attach the device log here for investigation? Thanks.

1 Like

Logs attached. Look for ‘Failed reading subscription info’.

5706838–597328–UnityAdsBug.txt (12.8 KB)

1 Like

Got it, it does indeed look like the same issue that we fixed, and no longer reproduced for us as the time. What product type is this receipt for? Are you checking to make sure it’s a Subscription receipt first?

Agreed with Jeff. I can reproduce this issue if I don’t use ‘if (item.definition.type == ProductType.Subscription)’ to check whether the product is a subscription product.

public void OnInitialized(IStoreController controller, IExtensionProvider extensions)
{
    m_AppleExtensions = extensions.GetExtension<IAppleExtensions> ();
    storeController = controller;
    storeExtensionProvider = extensions;

    m_GooglePlayStoreExtensions = extensions.GetExtension<IGooglePlayStoreExtensions>();

    Dictionary<string, string> introductory_info_dict = m_AppleExtensions.GetIntroductoryPriceDictionary();

    foreach (var item in controller.products.all)
    {
        if (item.availableToPurchase)
        {
            if (item.receipt != null)
            {
                if (item.definition.type == ProductType.Subscription)//Please use this to make sure it's a subscription receipt first.
                {
                    if (checkIfProductIsAvailableForSubscriptionManager(item.receipt)) {
                        string intro_json = (introductory_info_dict == null || !introductory_info_dict.ContainsKey(item.definition.storeSpecificId)) ? null : introductory_info_dict[item.definition.storeSpecificId];
                        subscriptionManager = new SubscriptionManager(item, intro_json);
                        SubscriptionInfo info = subscriptionManager.getSubscriptionInfo();
                    }
                    else {

                    }
                }
                else
                {
                    Debug.Log("the product is not a subscription product");
                }
            }
            else
            {
                Debug.Log("the product should have a valid receipt");
            }
        }
    }
}

5709088--597688--upload_2020-4-14_15-24-48.png

Thank you both. We are doing that check already (as you can see from the snippet below).

      [SIZE=4]  foreach (Product product in _storeController.products.all)
        {
            Debug.LogFormat("Product: {0}. HasReceipt: {1}. Type: {2}.", product.definition.id, product.hasReceipt, product.definition.type);
            if (product.definition.type == ProductType.Subscription)
            {
                if (!string.IsNullOrEmpty(product.receipt) && IsAValidSubscription(product.receipt))
                {
                    SubscriptionManager p = new SubscriptionManager(product, string.Empty);
                    try
                    {
                        SubscriptionInfo info = p.getSubscriptionInfo();
                        Debug.Log("Subscription. product id is: " + info.getProductId());
                    }
                    catch (Exception e)
                    {
                        Debug.LogErrorFormat("Failed reading subscription info. Error: {0}", e);
                    }
                }
            }
        }[/SIZE]
1 Like

Please provide the device logs that confirms. They will contain the Debug.Log information. Does this happen for all your subscriptions, and all your users? Your test users need to download the game via Google Play, AFTER opting into the test program from a browser on the device.

I am still waiting for this issue to be resolved.

Here is the log.

As I mentioned before,

Unity version is 2018.4.15f1.
IAP version is 1.23.1.

Do I have to update Unity version?

I have uploaded my apk to Google Play as internal testing, then download it and test it.