An example database that records the state of each purchase. You should use an obfuscator before storing any information to persistent storage. The obfuscator should use a key that is specific to the device and/or user. Otherwise an attacker could copy a database full of valid purchases and distribute it to others.
        /// <summary>
        /// Notifies the application of purchase state changes. The application
        /// can offer an item for sale to the user via
        /// <seealso cref="BillingService#requestPurchase(String)"/>. The BillingService
        /// calls this method after it gets the response. Another way this method
        /// can be called is if the user bought something on another device running
        /// this same app. Then Android Market notifies the other devices that
        /// the user has purchased an item, in which case the BillingService will
        /// also call this method. Finally, this method can be called if the item
        /// was refunded. </summary>
        /// <param name="purchaseState"> the state of the purchase request (PURCHASED,
        ///     CANCELED, or REFUNDED) </param>
        /// <param name="productId"> a string identifying a product for sale </param>
        /// <param name="orderId"> a string identifying the order </param>
        /// <param name="purchaseTime"> the time the product was purchased, in milliseconds
        ///     since the epoch (Jan 1, 1970) </param>
        /// <param name="developerPayload"> the developer provided "payload" associated with
        ///     the order </param>
        //JAVA TO C# CONVERTER WARNING: 'final' parameters are not allowed in .NET:
        //ORIGINAL LINE: public static void purchaseResponse(final android.content.Context context, final com.example.dungeons.Consts.PurchaseState purchaseState, final String productId, final String orderId, final long purchaseTime, final String developerPayload)
        public static void PurchaseResponse(Context context, Consts.PurchaseState purchaseState, string productId, string orderId, long purchaseTime, string developerPayload)
        {
            // Update the database with the purchase state. We shouldn't do that
            // from the main thread so we do the work in a background thread.
            // We don't update the UI here. We will update the UI after we update
            // the database because we need to read and update the current quantity
            // first.
            //JAVA TO C# CONVERTER TODO TASK: Anonymous inner classes are not converted to C# if the base type is not defined in the code being converted:
            new Thread(new Runnable(() =>
                {
                    PurchaseDatabase db = new PurchaseDatabase(context);
                    int quantity = db.UpdatePurchase(orderId, productId, purchaseState, purchaseTime, developerPayload);
                    db.Close();

                    // This needs to be synchronized because the UI thread can change the
                    // value of sPurchaseObserver.
                    lock (context)
                    {
                        if (sPurchaseObserver != null)
                        {
                            sPurchaseObserver.PostPurchaseStateChange(purchaseState, productId, quantity, purchaseTime, developerPayload);
                        }
                    }
                })).Start();
        }
        private void StartBillingStuff()
        {
            _handler = new Handler();
            _inAppBillingDemoObserver = new InAppBillingDemoPurchaseObserver(this, _handler);
            _billingService = new BillingService();
            _billingService.Context = this;
            ResponseHandler.Register(_inAppBillingDemoObserver);
            var inAppsSupported = _billingService.CheckBillingSupportedMethod(Consts.ITEM_TYPE_INAPP);
            var subscriptionsSupported = _billingService.CheckBillingSupportedMethod(Consts.ITEM_TYPE_SUBSCRIPTION);

            _purchaseDatabase = new PurchaseDatabase(this);
            OwnedItemsCursor = _purchaseDatabase.QueryAllPurchasedItems();
            StartManagingCursor(OwnedItemsCursor);
            var from = new string[] { PurchaseDatabase.PURCHASED_PRODUCT_ID_COL, PurchaseDatabase.PURCHASED_QUANTITY_COL };
            var to = new int[] { Resource.Id.itemName };
            _ownedItemsAdapter = new SimpleCursorAdapter(this, Resource.Layout.Main, OwnedItemsCursor, from, to);

            if (OwnedItems.Count == 0)
                ItemName.Text = "No purchases";
        }
 public DatabaseHelper(PurchaseDatabase outerInstance, Context context)
     : base(context, DATABASE_NAME, null, DATABASE_VERSION)
 {
     this.outerInstance = outerInstance;
 }