Java tutorial
package com.thunder.iap; /* * Copyright (C) 2015 Michele Paparella * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ import android.app.Activity; import android.app.PendingIntent; import android.content.ComponentName; import android.content.Context; import android.content.Intent; import android.content.IntentSender; import android.content.ServiceConnection; import android.os.Bundle; import android.os.IBinder; import android.os.RemoteException; import com.android.vending.billing.IInAppBillingService; import com.thunder.iap.listener.BuyItemListener; import com.thunder.iap.listener.BuySubscriptionListener; import com.thunder.iap.listener.ConsumePurchaseListener; import com.thunder.iap.listener.PurchasedItemsListener; import com.thunder.iap.listener.SkuDetailsListener; import com.thunder.iap.model.PurchasedItem; import org.json.JSONException; import org.json.JSONObject; import java.util.ArrayList; import java.util.HashMap; import java.util.Map; /** * a useful class that must be extended in order to use the In-App Purchases API from * an app */ public abstract class IAPActivity extends Activity { private IInAppBillingService mService; private BuyItemListener buyItemListener; private BuySubscriptionListener buySubscriptionListener; private static final int RC_INAPP_BUY = 1001; private static final int RC_SUBS_BUY = 9999; ServiceConnection mServiceConn = new ServiceConnection() { @Override public void onServiceDisconnected(ComponentName name) { mService = null; } @Override public void onServiceConnected(ComponentName name, IBinder service) { mService = IInAppBillingService.Stub.asInterface(service); } }; @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); //setContentView(R.layout.activity_main); Intent serviceIntent = new Intent("com.android.vending.billing.InAppBillingService.BIND"); serviceIntent.setPackage("com.android.vending"); bindService(serviceIntent, mServiceConn, Context.BIND_AUTO_CREATE); } @Override public void onDestroy() { super.onDestroy(); if (mService != null) { unbindService(mServiceConn); } } /** * * @param skuList the list of available skus * @param listener */ public void getSkuDetails(final ArrayList<String> skuList, final SkuDetailsListener listener) { new Thread(new Runnable() { @Override public void run() { Bundle querySkus = new Bundle(); querySkus.putStringArrayList("ITEM_ID_LIST", skuList); try { Bundle skuDetails = mService.getSkuDetails(3, getPackageName(), "inapp", querySkus); ArrayList<JSONObject> result = new ArrayList<JSONObject>(); int response = skuDetails.getInt("RESPONSE_CODE"); if (response == 0) { ArrayList<String> responseList = skuDetails.getStringArrayList("DETAILS_LIST"); for (String thisResponse : responseList) { JSONObject object = null; try { object = new JSONObject(thisResponse); } catch (JSONException e) { e.printStackTrace(); } //String sku = object.getString("productId"); //String price = object.getString("price"); //if (sku.equals("premiumUpgrade")) mPremiumUpgradePrice = price; //else if (sku.equals("gas")) mGasPrice = price; result.add(object); } listener.onResult(result); } else { listener.onServerError(skuDetails); } } catch (RemoteException e) { e.printStackTrace(); listener.onError(e); } } }).start(); } /** * * @param sku the item that the user wants to buy * @param developerPayload the developer payload string, more info here http://developer.android.com/training/in-app-billing/purchase-iab-products.html * @param buyItemListener */ public void buyItem(final String sku, final String developerPayload, final BuyItemListener buyItemListener) { this.buyItemListener = buyItemListener; new Thread(new Runnable() { @Override public void run() { try { Bundle buyIntentBundle = mService.getBuyIntent(3, getPackageName(), sku, "inapp", developerPayload); int response = buyIntentBundle.getInt("RESPONSE_CODE"); if (response == 0) { PendingIntent pendingIntent = buyIntentBundle.getParcelable("BUY_INTENT"); try { startIntentSenderForResult(pendingIntent.getIntentSender(), RC_INAPP_BUY, new Intent(), Integer.valueOf(0), Integer.valueOf(0), Integer.valueOf(0)); //the onSuccess callback of the listener will be called on the method onActivityResult } catch (IntentSender.SendIntentException e) { e.printStackTrace(); buyItemListener.onError(e); } } else { buyItemListener.onServerError(buyIntentBundle); } } catch (RemoteException e) { e.printStackTrace(); buyItemListener.onError(e); } } }).start(); } @Override protected void onActivityResult(int requestCode, int resultCode, Intent data) { if (requestCode == RC_INAPP_BUY) { //in app item bought int responseCode = data.getIntExtra("RESPONSE_CODE", 0); String purchaseData = data.getStringExtra("INAPP_PURCHASE_DATA"); String dataSignature = data.getStringExtra("INAPP_DATA_SIGNATURE"); if (resultCode == RESULT_OK) { try { JSONObject jo = new JSONObject(purchaseData); //String sku = jo.getString("productId"); if (buyItemListener != null) { buyItemListener.onSuccess(jo); } } catch (JSONException e) { e.printStackTrace(); } } else { if (buyItemListener != null) { buyItemListener.onError(new RuntimeException("Error during onActivityResult")); } } } if (requestCode == RC_SUBS_BUY) { //subscription bought int responseCode = data.getIntExtra("RESPONSE_CODE", 0); String purchaseData = data.getStringExtra("INAPP_PURCHASE_DATA"); String dataSignature = data.getStringExtra("INAPP_DATA_SIGNATURE"); if (resultCode == RESULT_OK) { try { JSONObject jo = new JSONObject(purchaseData); //String sku = jo.getString("productId"); if (buySubscriptionListener != null) { buySubscriptionListener.onSuccess(jo); } } catch (JSONException e) { e.printStackTrace(); } } else { if (buySubscriptionListener != null) { buySubscriptionListener.onError(new RuntimeException("Error during onActivityResult")); } } } } /** * returns a list of purchased items for the current user * @param purchasedItemsListener */ public void getInAppPurchasedItems(final PurchasedItemsListener purchasedItemsListener) { new Thread(new Runnable() { @Override public void run() { getPurchasedItems("inapp", purchasedItemsListener); } }).start(); } /** * consume a purchase * @param purchaseToken * @param consumePurchaseListener */ public void consumePurchase(final String purchaseToken, final ConsumePurchaseListener consumePurchaseListener) { new Thread(new Runnable() { @Override public void run() { try { int response = mService.consumePurchase(3, getPackageName(), purchaseToken); if (response == 0) { consumePurchaseListener.onSuccess(); } else { consumePurchaseListener.onServerError(response); } } catch (RemoteException e) { e.printStackTrace(); consumePurchaseListener.onError(e); } } }).start(); } /** * this methods is needed when a user wants to buy a subscription * @param sku * @param developerPayload * @param buySubscriptionListener */ public void buySubscription(final String sku, final String developerPayload, final BuySubscriptionListener buySubscriptionListener) { this.buySubscriptionListener = buySubscriptionListener; new Thread(new Runnable() { @Override public void run() { try { Bundle bundle = mService.getBuyIntent(3, getPackageName(), sku, "subs", developerPayload); PendingIntent pendingIntent = bundle.getParcelable("BUY_INTENT"); if (bundle.getInt("RESPONSE_CODE") == 0) { // Start purchase flow (this brings up the Google Play UI). // Result will be delivered through onActivityResult(). try { startIntentSenderForResult(pendingIntent.getIntentSender(), RC_SUBS_BUY, new Intent(), Integer.valueOf(0), Integer.valueOf(0), Integer.valueOf(0)); } catch (IntentSender.SendIntentException e) { e.printStackTrace(); buySubscriptionListener.onError(e); } } else { buySubscriptionListener.onServerError(bundle); } } catch (RemoteException e) { e.printStackTrace(); buySubscriptionListener.onError(e); } } }).start(); } /** * returns the purchased subscriptions * @param purchasedItemsListener */ public void getPurchasedSubscriptions(final PurchasedItemsListener purchasedItemsListener) { new Thread(new Runnable() { @Override public void run() { getPurchasedItems("subs", purchasedItemsListener); } }).start(); } /** * returns the purchased items for a user * @param itemType * @param purchasedItemsListener */ public void getPurchasedItems(String itemType, PurchasedItemsListener purchasedItemsListener) { try { Bundle ownedItems = mService.getPurchases(3, getPackageName(), itemType, null); int response = ownedItems.getInt("RESPONSE_CODE"); if (response == 0) { ArrayList<String> ownedSkus = ownedItems.getStringArrayList("INAPP_PURCHASE_ITEM_LIST"); ArrayList<String> purchaseDataList = ownedItems.getStringArrayList("INAPP_PURCHASE_DATA_LIST"); ArrayList<String> signatureList = ownedItems.getStringArrayList("INAPP_DATA_SIGNATURE_LIST"); String continuationToken = ownedItems.getString("INAPP_CONTINUATION_TOKEN"); Map<String, PurchasedItem> skuToPurchasedItem = new HashMap<String, PurchasedItem>(); for (int i = 0; i < purchaseDataList.size(); ++i) { String purchaseData = purchaseDataList.get(i); String signature = signatureList.get(i); String sku = ownedSkus.get(i); // do something with this purchase information // e.g. display the updated list of products owned by user skuToPurchasedItem.put(sku, new PurchasedItem(purchaseData, signature, sku)); } while (continuationToken != null) { try { ownedItems = mService.getPurchases(3, getPackageName(), itemType, continuationToken); response = ownedItems.getInt("RESPONSE_CODE"); if (response == 0) { ownedSkus = ownedItems.getStringArrayList("INAPP_PURCHASE_ITEM_LIST"); purchaseDataList = ownedItems.getStringArrayList("INAPP_PURCHASE_DATA_LIST"); signatureList = ownedItems.getStringArrayList("INAPP_DATA_SIGNATURE_LIST"); continuationToken = ownedItems.getString("INAPP_CONTINUATION_TOKEN"); for (int i = 0; i < purchaseDataList.size(); ++i) { String purchaseData = purchaseDataList.get(i); String signature = signatureList.get(i); String sku = ownedSkus.get(i); // do something with this purchase information // e.g. display the updated list of products owned by user skuToPurchasedItem.put(sku, new PurchasedItem(purchaseData, signature, sku)); } } else { purchasedItemsListener.onServerError(ownedItems); } } catch (RemoteException e) { e.printStackTrace(); purchasedItemsListener.onError(e); } } // if continuationToken != null, call getPurchases again // and pass in the token to retrieve more items } else { purchasedItemsListener.onServerError(ownedItems); } } catch (RemoteException e) { e.printStackTrace(); purchasedItemsListener.onError(e); } } }