Xamarin.InAppBilling - “错误可用库存:System.NullReferenceException”

时间:2015-11-28 18:37:04

标签: xamarin in-app-purchase xamarin.android in-app-billing

注意:我主要是在这里发布这个问题,以便将谷歌编入索引并让一些贫穷的灵魂陷入深陷这个混乱的麻烦,但却发现这不是他们自己的错。这个问题的一个可接受的答案是我可以使用的解决方法或Xamarin / SimpleJson的某人,这是一个错误,它将被修复。

我已经成功使用Xamarin.InAppBilling超过一年了(在真正的Google Play商店购买正常工作)。我们最近开始重新测试此功能(由于重构)并在查询我们的产品库存时遇到此异常(即使使用静态响应测试产品Skus):

Error Available Inventory: System.NullReferenceException: Object reference not set to an instance of an object
  at Xamarin.InAppBilling.PocoJsonSerializerStrategy.DeserializeObject (System.Object value, System.Type type) [0x0047a] in <filename unknown>:0 
  at Xamarin.InAppBilling.SimpleJson.DeserializeObject (System.String json, System.Type type, IJsonSerializerStrategy jsonSerializerStrategy) [0x0003d] in <filename unknown>:0 
  at Xamarin.InAppBilling.SimpleJson.DeserializeObject[T] (System.String json) [0x00000] in <filename unknown>:0 
  at System.Linq.Enumerable+WhereSelectEnumerableIterator`2[TSource,TResult].MoveNext () [0x00064] in /Users/builder/data/lanes/2098/3efa14c4/source/mono/external/referencesource/System.Core/System/Linq/Enumerable.cs:285 
  at System.Collections.Generic.List`1[T]..ctor (IEnumerable`1 collection) [0x0008b] in /Users/builder/data/lanes/2098/3efa14c4/source/mono/external/referencesource/mscorlib/system/collections/generic/list.cs:105 
  at System.Linq.Enumerable.ToList[TSource] (IEnumerable`1 source) [0x00011] in /Users/builder/data/lanes/2098/3efa14c4/source/mono/external/referencesource/System.Core/System/Linq/Enumerable.cs:835 
  at Xamarin.InAppBilling.InAppBillingHandler+<QueryInventoryAsync>c__AnonStorey0.<>m__0 () [0x00092] in <filename unknown>:0 

我已经撤消了Xamarin的In App Billing代码,尤其是Xamarin.InAppBilling.InAppBillingHandler.QueryInventoryAsync(IList<string> skuList, string itemType)方法。

它的作用是查询Google Play结算API以获取sku详细信息,然后反序列化返回的DETAILS_LIST json对象。这是代码抛出NullReferenceException的地方。所有这些都超出了我的控制范围,因此我使用了此代码的修改后的副本来获取原始json,当然它对我来说非常好看。代码:

var service = _serviceConnection.Service;
Task.Factory.StartNew<IList<Product>>( () => {
    IList<Product> result;
    try
    {
        Bundle bundle = new Bundle();
        bundle.PutStringArrayList( "ITEM_ID_LIST", skus );
        Bundle skuDetails = service.GetSkuDetails( 3, this.Activity.PackageName, ItemType.Product, bundle );
        int responseCode = skuDetails.GetInt( "RESPONSE_CODE" );
        if (responseCode != 0)
        {
            ViewModel.ShowTransactionError( "Error querying inventory: " + TranslateResponseCode( responseCode ) );
            result = null;
        }
        else
        {
            IList<string> stringArrayList = skuDetails.GetStringArrayList( "DETAILS_LIST" );
            result = null;
            if (stringArrayList != null)
            {
                Console.WriteLine("DETAILS_LIST: " + string.Join("\n - ", stringArrayList));
                result = stringArrayList.Select(x => JsonConvert.DeserializeObject<Product>(x)).ToList();
            }                        
        }
    } catch (Exception ex)
    {
        ViewModel.ShowTransactionError( "Error querying inventory: " + ex.ToString() );
        result = null;
    }
    return result;
} )

JSON:

DETAILS_LIST: {"title":"Sample Title","price":"0,93 €","type":"inapp","description":"Sample description for product: android.test.canceled.","price_amount_micros":933038,"price_currency_code":"EUR","productId":"android.test.canceled"}
 - {"title":"Sample Title","price":"0,93 €","type":"inapp","description":"Sample description for product: android.test.item_unavailable.","price_amount_micros":933038,"price_currency_code":"EUR","productId":"android.test.item_unavailable"}
 - {"title":"Sample Title","price":"0,93 €","type":"inapp","description":"Sample description for product: android.test.purchased.","price_amount_micros":933038,"price_currency_code":"EUR","productId":"android.test.purchased"}
 - {"title":"Sample Title","price":"0,93 €","type":"inapp","description":"Sample description for product: android.test.refunded.","price_amount_micros":933038,"price_currency_code":"EUR","productId":"android.test.refunded"}
 - {"title":"Boat Upgrade (Rowing in Motion - Solo)","price":"69,90 €","type":"inapp","description":"Analyze and Record an unlimited number of strokes per rowing session.","price_amount_micros":69900000,"price_currency_code":"EUR","productId":"com.rowinginmotion.mobile.boatapp.droid.solo.boat"}
 - {"title":"Coach Upgrade (Rowing in Motion - Solo)","price":"98,77 €","type":"inapp","description":"Receive unlimited live data from a boat using a mobile WiFi.","price_amount_micros":98770000,"price_currency_code":"EUR","productId":"com.rowinginmotion.mobile.boatapp.droid.solo.coach"}

所以我认为SimpleJson / PocoJson在那里有任何串行器都有问题。看起来像是图书馆中的一个错误,而不是我身边的错误(通过他们的核对清单和所有在这里看上帝的工作)。

我使用JSON.NET问题是他们的Product类显然没有默认构造函数(什么?!,我已经和IL一起工作了很多年而从未见过喜欢这个的东西),但有一个CompilerGeneratedAttribute坚持下去。我的产品需要是该类的实例,以便我可以将它们传递回API ...

1 个答案:

答案 0 :(得分:2)

linker再次点击。 PocoJsonSerializerStrategy使用了大量的反射,所以这是我的第二次猜测,经过things you need to get right for IAPs to work的长列表。

将此添加到您的.csproj,您就可以开始了。

<AndroidLinkSkip>Xamarin.InAppBilling</AndroidLinkSkip>

令人失望的是,Xamarin并没有让他们自己的库链接器证明......

这个问题很容易花费我一两天的时间,特别是因为有很多subtle ways,其中In-App-Billing会破坏你应该首先检查(特别是我们移动了很多IAP)从一个Activity到一个Fragment的逻辑,所以这也必须进行测试)。

旁注:我等待3x2h是徒劳的,因为我的测试设备上可以使用我的仪表化版本的Google Play Alpha频道更新。对于 me ,我可以使用从Xamarin Studio(甚至是Debug版本)部署的版本成功测试和运行IAP。这并不意味着这对你也有用。