While implementing In App Subscriptions i found out that the process of implementing it was not that complicated, but there were some hidden facts that took me time to figure out. And as there is no much examples out there about this case i decided to write an article that may be helpful for someone dealing with In App Billing.
First of all you must have a Google Play Developer Account for implementing and testing In App related cases**.** Unfortunately you won’t be able to run InApp Subscription without publishing a signed APK (at least on Beta or Alpha testing) on Play Store.
For initializing In App Billing you will need a public key. For getting it you must create an application from play store by clicking on Add new Application, filling required fields and clicking on Upload APK:
This will redirect you to the newly created application page (You can fill later on the details for app publishing). Navigate to Services & APIs and copy YOUR LICENSE KEY FOR THIS APPLICATION as we will need it later on:
Than you have to upload a signed APK in Alpha or Beta Testing_(in this example i use Alpha Testing)_ by clicking on APK tab > Alpha Testing > Upload your first APK to Alpha:
Google will process the APK and it will take some hours till it is published.
You must keep the version of apk in your device same with the one that is published, otherwise the In App Billing won’t work
After the apk is published, you will be able to create a Subscription (Product):
You cannot create a product if app is unpublished
Clicking on Add new product will show a popup screen asking you to write details of your product:
As we are going to create a subscription, we choose Subscription tab. Product ID is a unique id to identify your product. When you want to consume the product from play store, you will use this unique id to identify it.
After creating a product, a page for filling the details of the product will be shown. Fill them based on your needs and now you are ready to go.
Google provides an easy to use library that is able to handle the payment,subscriptions and querying tasks. You can download it from here or from the {SDK_PATH}\extras\google\play_billing\samples.
You must create a folder under main called aidl and inside it create a package named as: com.android.vending.billing. Inside that package you will have to put AIDL(IInAppBillingService.aidl) file found in the downloaded sample or locally from the above told google extras path. You will also have to copy the other files in your projects package (it doesnt matter where, you can create a purchaseUtils package and put inside it). At the time i wrote there were 8 files, in case you forget any: {IabBroadcastReceiver, IabException, IabHelper, IabResult, Inventory, Purchase, Security and SkuDetails}.
Do not forget to add BILLING permissions to AndroidManifest.xml:
<uses-permission android:name=”com.android.vending.BILLING” />
Later on you need to create an IabHelper instance and initialize In App Billing on OnCreate() or wherever it satisfies your needs:
IabHelper iabHelper = new IabHelper(context, base64EncodedPublicKey);iabHelper.startSetup(new IabHelper.OnIabSetupFinishedListener() {@Overridepublic void onIabSetupFinished(IabResult result) {if (result.isFailure()) {Log.d("YOUR_TAG", "Problem setting up In-app Billing: " + result);dispose();}}});
/*** Method for releasing resources (dispose of object)*/public void dispose() {if (iabHelper != null) {try {iabHelper.dispose();} catch (IabHelper.IabAsyncInProgressException e) {e.printStackTrace();}iabHelper = null;}}
It is a good behavior you also enable debug logs(optionally you can give a tag name also) as it will help you debug faster:
iabHelper.enableDebugLogging(true, "YOUR_TAG");
To launch Subscription panel we have to call launchSubscriptionPurchaseFlow() method. You need to provide the Product id(subscriptionType) you wrote when you created a new Product and a REQUEST_CODE(it can be any random integer) so it can catch it onActivityResult() method:
try {iabHelper.launchSubscriptionPurchaseFlow((Activity) context,subscriptionType,REQUEST_CODE,new IabHelper.OnIabPurchaseFinishedListener() {@Overridepublic void onIabPurchaseFinished(IabResult result, Purchase info) {if (result.isFailure()) {Log.e("TEST", "Error purchasing: " + result);return;}if (info.getSku().equals(subscriptionType)) {if(subscriptionFinishedListener != null){subscriptionFinishedListener.onSuccess();}Log.e("TEST", "Thank you for upgrading to premium!");}}},payload);} catch (IabHelper.IabAsyncInProgressException e) {e.printStackTrace();}
then you handle it with a help of handleActivityResult() method:
@Overridepublic void onActivityResult(int requestCode, int resultCode, Intent data) {if (!iabHelper.handleActivityResult(requestCode, resultCode, data)) {super.onActivityResult(requestCode, resultCode, data);}}
You can also get subscription details for displaying or verifying them through queryInventoryAsync() method. It queries details asynchronously, hence it is safe to call it from UI thread:
try {iabHelper.queryInventoryAsync(true, null, skuIdsList, new IabHelper.QueryInventoryFinishedListener() {@Overridepublic void onQueryInventoryFinished(IabResult result, Inventory inventory) {if (result.isFailure()) {Log.d("TEST", "Problem querying inventory: " + result);dispose();return;}
for (String skuId : skuIdsList) {
SkuDetails sku = inventory.getSkuDetails(skuId);
if (sku.getSku().equals(skuId)) {
Log._e_("YOUR\_TAG", "Product Price:" + sku.getPrice());
}
}
}
});} catch (IabHelper.IabAsyncInProgressException e) {Log.e("TEST", "EXCEPTION:" + e.getMessage());}
skuIdsList is a List of Strings where multiple Product Ids are stored
For testing you will need to add your testing email on LICENSE TESTING located on Settings tab of Google Play Account Details. This way you won’t get charged when you subscribe:
Note that you cannot subscribe with the same Developer Account you used to publish the app. You must open your play store on device with different account
Thats all!
Here is a gist i wrote about In App Subscription. You can include that SubscriptionUtil.class in your app. Than you can initialize it’s instance in onCreate() method or somewhere you find it most suitable for your case:
subscriptionUtil = new SubscriptionUtil(context);
release resources on onDestroy():
@Overridepublic void onDestroy() {super.onDestroy();if (subscriptionUtil != null) {subscriptionUtil.dispose();}}
handle requests on onActivityResult():
@Overridepublic void onActivityResult(int requestCode, int resultCode, Intent data) {if (!subscriptionUtil.getIabHelper().handleActivityResult(requestCode, resultCode, data)) {super.onActivityResult(requestCode, resultCode, data);}}
If you want to consume subscription types, create a list with Product Ids of those subscriptions you want to consume and send them as request using getSkuDetailsList() method:
ArrayList<String> skuRequestList = new ArrayList<>();skuRequest.add("first_product_id");skuRequest.add("second_product_id");
subscriptionUtil.getSkuDetailsList(skuRequestList, new SubscriptionUtil.SubscriptionInventoryListener() {@Overridepublic void onQueryInventoryFinished(ArrayList<SkuDetails> skuList) {//Do whatever you want with list of SkuDetails}});
If you want to proceed with subscription, you can send an object of that subscription(SkuDetails object) to initSubscription() method:
subscriptionUtil.initSubscription(skuDetailsObject.getSku(), new SubscriptionUtil.SubscriptionFinishedListener() {@Overridepublic void onSuccess() {//Do whatever you want on subscription success }});
And you are good to go :)