I am attempting to [implement Amazon In-App Purchases in an Android project using Xamarin.
The setup
Amazon's official Xamarin SDK doesn't support the newer 64-bit devices so I created my own Java library binding using Amazon's Java SDK. (Documentation for the Java version)
The binding generated by Xamarin for PurchasingService
looks like this:
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);
}
}
And for the PurchasingListener
interface:
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);
}
}
I also made sure that the Android manifest was modified with:
<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>
The Amazon App Tester is installed on my Kindle and configured with the following test data:
{
"IAP_ID":
{
"description":"One year Subscription",
"title":"My Subscription",
"itemType":"SUBSCRIPTION",
"price":20.00,
"subscriptionParent":"org.company.appid"
}
}
And I have a skeleton of a class to test that the system works:
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");
}
}
The test run
I am attempting to run this on my 5th Gen Kindle Fire. When the app launches, the user is prompted with the Amazon IAP prompt as expected. If the purchase is performed, it goes through and the transaction correctly appears in the Amazon App Tester app.
The problem
I have breakpoints setup in the callback methods. These breakpoints are never triggered. Neither do the Debug.WriteLine
calls show up in the Application Output. It appears that my callback methods are not being called.