亚马逊IAP没有呼叫监听器回叫(Kindle Fire,Xamarin)

时间:2017-08-07 19:48:15

标签: android xamarin xamarin.android kindle-fire amazon-appstore

我正在尝试[使用Xamarin在Android项目中实施Amazon In-App Purchase。

设置

亚马逊的官方Xamarin SDK不支持较新的64位设备,因此我使用亚马逊的Java SDK创建了own Java library binding。 (Documentation for the Java version

Xamarin为PurchasingService生成的绑定如下所示:

namespace Com.Amazon.Device.Iap
{
    [Register ("com/amazon/device/iap/PurchasingService", DoNotGenerateAcw = true)]
    public sealed class PurchasingService : Object
    {
        //
        // Static Fields
        //
        private static IntPtr IS_SANDBOX_MODE_jfieldId;

        [Register ("SDK_VERSION")]
        public const string SdkVersion = "2.0.76.4";

        internal static IntPtr java_class_handle;

        private static IntPtr id_getUserData;

        private static IntPtr id_getProductData_Ljava_util_Set_;

        private static IntPtr id_getPurchaseUpdates_Z;

        private static IntPtr id_notifyFulfillment_Ljava_lang_String_Lcom_amazon_device_iap_model_FulfillmentResult_;

        private static IntPtr id_purchase_Ljava_lang_String_;

        private static IntPtr id_registerListener_Landroid_content_Context_Lcom_amazon_device_iap_PurchasingListener_;

        //
        // Static Properties
        //
        internal static IntPtr class_ref {
            get;
        }

        [Register ("IS_SANDBOX_MODE")]
        public static bool IsSandboxMode {
            get;
        }

        public static RequestId UserData {
            [Register ("getUserData", "()Lcom/amazon/device/iap/model/RequestId;", "GetGetUserDataHandler")]
            get;
        }

        //
        // Properties
        //
        protected override IntPtr ThresholdClass {
            get;
        }

        protected override Type ThresholdType {
            get;
        }

        //
        // Constructors
        //
        internal PurchasingService (IntPtr javaReference, JniHandleOwnership transfer);

        //
        // Static Methods
        //
        [Register ("getProductData", "(Ljava/util/Set;)Lcom/amazon/device/iap/model/RequestId;", "")]
        public static RequestId GetProductData (ICollection<string> p0);

        [Register ("getPurchaseUpdates", "(Z)Lcom/amazon/device/iap/model/RequestId;", "")]
        public static RequestId GetPurchaseUpdates (bool p0);

        [Register ("notifyFulfillment", "(Ljava/lang/String;Lcom/amazon/device/iap/model/FulfillmentResult;)V", "")]
        public static void NotifyFulfillment (string p0, FulfillmentResult p1);

        [Register ("purchase", "(Ljava/lang/String;)Lcom/amazon/device/iap/model/RequestId;", "")]
        public static RequestId Purchase (string p0);

        [Register ("registerListener", "(Landroid/content/Context;Lcom/amazon/device/iap/PurchasingListener;)V", "")]
        public static void RegisterListener (Context p0, IPurchasingListener p1);
    }
}

对于PurchasingListener界面:

namespace Com.Amazon.Device.Iap
{
    [Register ("com/amazon/device/iap/PurchasingListener", "", "Com.Amazon.Device.Iap.IPurchasingListenerInvoker")]
    public interface IPurchasingListener : IJavaObject, IDisposable
    {
        //
        // Methods
        //
        [Register ("onProductDataResponse", "(Lcom/amazon/device/iap/model/ProductDataResponse;)V", "GetOnProductDataResponse_Lcom_amazon_device_iap_model_ProductDataResponse_Handler:Com.Amazon.Device.Iap.IPurchasingListenerInvoker, AmazonIAP")]
        void OnProductDataResponse (ProductDataResponse p0);

        [Register ("onPurchaseResponse", "(Lcom/amazon/device/iap/model/PurchaseResponse;)V", "GetOnPurchaseResponse_Lcom_amazon_device_iap_model_PurchaseResponse_Handler:Com.Amazon.Device.Iap.IPurchasingListenerInvoker, AmazonIAP")]
        void OnPurchaseResponse (PurchaseResponse p0);

        [Register ("onPurchaseUpdatesResponse", "(Lcom/amazon/device/iap/model/PurchaseUpdatesResponse;)V", "GetOnPurchaseUpdatesResponse_Lcom_amazon_device_iap_model_PurchaseUpdatesResponse_Handler:Com.Amazon.Device.Iap.IPurchasingListenerInvoker, AmazonIAP")]
        void OnPurchaseUpdatesResponse (PurchaseUpdatesResponse p0);

        [Register ("onUserDataResponse", "(Lcom/amazon/device/iap/model/UserDataResponse;)V", "GetOnUserDataResponse_Lcom_amazon_device_iap_model_UserDataResponse_Handler:Com.Amazon.Device.Iap.IPurchasingListenerInvoker, AmazonIAP")]
        void OnUserDataResponse (UserDataResponse p0);
    }
}

我还确保Android清单已修改为:

<receiver android:name = "com.amazon.device.iap.ResponseReceiver" >
    <intent-filter>
        <action android:name = "com.amazon.inapp.purchasing.NOTIFY"
          android:permission = "com.amazon.inapp.purchasing.Permission.NOTIFY" />
    </intent-filter>
</receiver>

Amazon App Tester安装在我的Kindle上,并配置了以下测试数据:

{
    "IAP_ID":
    {
      "description":"One year Subscription",
      "title":"My Subscription",
      "itemType":"SUBSCRIPTION",
      "price":20.00,
      "subscriptionParent":"org.company.appid"
    }
}

我有一个类的骨架来测试系统的工作原理:

public class AmazonIAPController : Java.Lang.Object, IPurchasingListener
{
    const string ProductId = "IAP_ID";
    private Activity uiActivity;

    public AmazonIAPController()
    {
    }

    public void SetupIAP(Activity activity) {
        uiActivity = activity;
        PurchasingService.RegisterListener(uiActivity, this);

        // test that the Amazon system works
        PurchasingService.Purchase(ProductId);
    }

    public void OnResume(Activity activity) {
        uiActivity = activity;
        PurchasingService.RegisterListener(uiActivity, this);

        //PurchasingService.UserData;
        PurchasingService.GetPurchaseUpdates(false);
        PurchasingService.GetProductData(new string[] { ProductId });

    }

    public void OnProductDataResponse(ProductDataResponse response) {
        var status = response.GetRequestStatus();

        Debug.WriteLine("*****OnProductDataResponse");
    }

    public void OnPurchaseResponse(PurchaseResponse response) {
        var status = response.GetRequestStatus();
        Debug.WriteLine("*****OnPurchaseResponse");
    }

    public void OnPurchaseUpdatesResponse(PurchaseUpdatesResponse response) {
        var status = response.GetRequestStatus();
        Debug.WriteLine("*****OnPurchaseUpdatesResponse");
    }

    public void OnUserDataResponse(UserDataResponse response) {
        var status = response.GetRequestStatus();
        Debug.WriteLine("*****OnUserDataResponse");
    }
}

试运行

我试图在我的第五代Kindle Fire上运行它。应用程序启动时,将按预期向用户提示Amazon IAP提示。如果执行购买,则会完成购买并且交易正确显示在Amazon App Tester应用程序中。

问题

我在回调方法中设置了断点。永远不会触发这些断点。 Debug.WriteLine调用也不会显示在应用程序输出中。看来我的回调方法没有被调用。

1 个答案:

答案 0 :(得分:2)

问题的根源是Android清单条目与Xamarin如何生成带有代码属性的清单条目相冲突。

为了解决这个问题,我从清单中删除了上述条目,并在Java绑定项目中创建了一个附加文件,其中包含ResponseReciever的部分类和相关的清单属性,如下所示:

using System;
using Android.App;
using Android.Content;

namespace Com.Amazon.Device.Iap
{
    [BroadcastReceiver(Name = "com.amazon.device.iap.ResponseReceiver")]
    [IntentFilter(new[] { "com.amazon.inapp.purchasing.NOTIFY" })]
    public partial class ResponseReceiver
    {

    }
}

此后,清单条目已正确生成,预期的回调开始起作用。

注意:

您可能会注意到清单XML中的android:permission条目不在上述属性中。我无法找到该引用,但我记得在某个地方看到这个条目不仅不需要让SDK工作,而且根据{{action它实际上不是有效属性dependencies { classpath 'com.android.tools.build:gradle:2.2.3' // I added this: classpath 'com.google.gms:google-services:3.1.0' } .. allprojects { repositories { // changed the + to 10.2.0 compile "com.google.android.gms:play-services-auth:10.2.0" compile "com.google.android.gms:play-services-identity:10.2.0" } } // at end of the promptForReleaseKeyPassword function, add this: def promptForReleaseKeyPassword() { ... apply plugin: 'com.google.gms.google-services' } 3}}