Monetization is one of the most important aspects of distributing your product to the rest of the world.
Android, being so widespread, provides ways for users to purchase products from within your app: this is referred to as In-app Billing. Through this set of APIs, developers can offer two types of products:
Your application accesses the In-app Billing service using an API that is exposed by the Google Play app that is installed on the device. The Google Play app then conveys billing requests and responses between your application and the Google Play server. In practice, your application never directly communicates with the Google Play server. Instead, your application sends billing requests to the Google Play app over interprocess communication (IPC) and receives responses from the Google Play app. Your application does not manage any network connections between itself and the Google Play server.
You must have a Google payments merchant account to use the In-app Billing service on Google Play.
The In-app Billing API provides the following features:
In-app products are the digital products that you offer for sale to users from inside your application. Examples of digital products include in-game currency, application feature upgrades that enhance the user experience, and new content for your application. You can use In-app Billing to sell only digital content. You define your products using the Google Play Console.
The Play Console is where you can publish your In-app Billing application and manage the various in-app products that are available for purchase from your application. You can create a product list of digital products that are associated with your application, including products for one-time purchase and recurring subscriptions. You can define information for each product such as the following:
Google Play Purchase Flow. To initiate a purchase, your application sends a billing request for a specific in-app product. Google Play then handles all of the checkout details for the transaction, including requesting and validating the form of payment and processing the financial transaction.
When the checkout process is complete, Google Play sends your application the purchase details, such as the order number, the order date and time, and the price paid. At no point does your application have to handle any financial transactions; that role belongs to Google Play.
To simplify development with the In-app Billing API, you can use the Play Billing Library. This library is an in-app billing client developed as a wrapper on top of the Android Interface Definition Language file that interacts with the In-app Billing API. You can use the Play Billing Library to help you focus your development effort on app logic, such as listing products, displaying product details, or launching purchase flows. The Play Billing Library provides an easier to use alternative to developing with the Android Interface Definition Language file.
So, preparations steps are below
Merchant account and in-app purchase products
To test your android app for in-app billing, you need to log into your Google Play Developer Console. If you have not registered with Google as an app publisher, then you will first of all do that.
To create a new Google Merchant Account, go the Settings menu option inside your Developer console page. Then select Account details and scroll down to the bottom of the page. Click on Create merchant account button. Follow the remaining instruction to finish up. Or you can manage your Merchant account at Google Payment Centre -> Settings.
To add in-app purchase products go to the YOUR_APP > Store presence > In-app products menu. There are two type of in-app purchase products – Managed product and Subscription products. We will focus on the Managed Product. Click on Add new product button. Add the title and description for the product. Set a price for the product. When you are done, make sure you click on the Inactive button and activate this product.
I have add the following products as shown in the screen shot below.
Create android application
We are going to update the AndroidManifest.xml file by adding the following user permissions
<uses-permission android:name="com.android.vending.BILLING" /> <uses-permission android:name="android.permission.INTERNET" />
Next step is adding the aidl file to your project.
The IInAppBillingService.aidl
is an Android Interface Definition Language (AIDL) file that defines the interface to the In-app Billing service. You can use this interface to make billing requests by invoking interprocess communication (IPC) method calls.
You can find the IInAppBillingService.aidl
file in the Trivial Drive sample app. To add the In-app Billing library to your project, follow these instructions:
aidl
under src/main
. To create the aidl directory, right-click on the app node in the project tool window, selecting the New -> Folder -> AIDL Folder menu option. Within the Project tool window the aidl
folder should now be listed.com.android.vending.billing
in this directory. Right-click on the aidl
folder and select the New -> Package menu item. In the resulting dialog, enter com.android.vending.billing into the text field and click on OK.IInAppBillingService.aidl
file into this package.IInAppBillingService.java
in the gen/
directory of your project.util/
directory of the Trivial Drive sample to your project. Remember to change the package name declarations in those files accordingly so that your project compiles.To get going with the Play Billing library you need to begin by adding the following dependency to your application-level build.gradle file:
compile 'com.android.billingclient:billing:1.0'
The Play Billing Library provides us with the functionality to consume any items which have previously purchased - this can be useful for tangible things such as power-ups in games or timed unlocking of features. This can be done by using the consumeAsync()
method and as parameters, this method takes the purchase token (which would have been received when the item was purchased) and an instance of the ConsumeResponseListener
class as a callback for the result of the consumption.
IABHelper
is just a wrapper utility class, which intends to give you an example of how IInAppBillingService
is to be used. IInAppBillingService
is a part of in-app billing API. It is used to perform purchases and check statuses. You can use this service directly and forget about the helper class. Many people find IABHelper
simpler and they use it as-is. Other people use service and ignore helper class completely.
Following is a example of in-app purchase activity with query and consume flow.
public class PurchaseActivity extends AppCompatActivity { Activity activity = PurchaseActivity.this; private String TAG = Constants.TAG; @BindView(R.id.rvItems) RecyclerView rvItems; @BindView(R.id.llLoader) LinearLayout llLoader; @BindView(R.id.llEmptyList) LinearLayout llEmptyList; @BindView(R.id.llNoInternet) LinearLayout llNoInternet; @BindView(R.id.btnContinue) Button btnContinue; LinearLayoutManager lm; ItemAdapter adapter; List<String> additionalSkuList = Arrays.asList("1", "2", "3"); int RC_REQUEST = 10001; IabHelper mHelper; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_purchase); ButterKnife.bind(this); String base64EncodedPublicKey = "_BASE64_KEY_"; mHelper = new IabHelper(this, base64EncodedPublicKey); mHelper.startSetup(new IabHelper.OnIabSetupFinishedListener() { public void onIabSetupFinished(IabResult result) { if (!result.isSuccess()) { Toast.makeText(activity, "Problem setting up In-app Billing: " + result, Toast.LENGTH_SHORT).show(); } else { loadProducts(); } } }); } private void loadProducts() { try { mHelper.queryInventoryAsync(true, additionalSkuList, null, new IabHelper.QueryInventoryFinishedListener() { @Override public void onQueryInventoryFinished(IabResult result, Inventory inv) { List<PurchaseItem> items = new ArrayList<>(); PurchaseItem item; for (String s : additionalSkuList) { item = new PurchaseItem(); item.setTitle(inv.getSkuDetails(s).getTitle()); item.setDescription(inv.getSkuDetails(s).getDescription()); item.setPrice(inv.getSkuDetails(s).getPrice()); item.setId(inv.getSkuDetails(s).getSku()); items.add(item); } llLoader.setVisibility(View.GONE); if (items.isEmpty()) { rvItems.setVisibility(View.GONE); llEmptyList.setVisibility(View.VISIBLE); } else { llEmptyList.setVisibility(View.GONE); rvItems.setVisibility(View.VISIBLE); lm = new LinearLayoutManager(activity, LinearLayoutManager.VERTICAL, false); rvItems.setLayoutManager(lm); adapter = new ItemAdapter(activity, items); rvItems.setAdapter(adapter); } } }); } catch (IabHelper.IabAsyncInProgressException e) { e.printStackTrace(); } } @Override public void onDestroy() { super.onDestroy(); if (mHelper != null) try { mHelper.dispose(); } catch (IabHelper.IabAsyncInProgressException e) { e.printStackTrace(); } catch (IllegalArgumentException e) { e.printStackTrace(); } mHelper = null; } @Override protected void onActivityResult(int requestCode, int resultCode, Intent data) { if (!mHelper.handleActivityResult(requestCode, resultCode, data)) { // not handled, so handle it ourselves (here's where you'd // perform any handling of activity results not related to in-app // billing... super.onActivityResult(requestCode, resultCode, data); } } @OnClick(R.id.btnContinue) public void clickContinue(View v) { PurchaseItem item = adapter.getSelected(); try { mHelper.launchPurchaseFlow(activity, item.getId(), RC_REQUEST, mPurchaseFinishedListener, ""); } catch (IabHelper.IabAsyncInProgressException e) { Log.d(TAG, "onProductClick: " + e.getMessage()); } } IabHelper.OnIabPurchaseFinishedListener mPurchaseFinishedListener = new IabHelper.OnIabPurchaseFinishedListener() { @Override public void onIabPurchaseFinished(IabResult result, me.proft.sandbox.utils.billing.Purchase purchase) { Log.d(TAG, "Purchase finished: " + result + ", purchase: " + purchase); // if we were disposed of in the meantime, quit. if (mHelper == null) return; if (result.isFailure()) { Toast.makeText(activity, "Error purchasing: " + result, Toast.LENGTH_SHORT).show(); return; } Log.d(TAG, "Purchase successful." + purchase); try { mHelper.consumeAsync(purchase, mConsumeFinishedListener); } catch (IabHelper.IabAsyncInProgressException e) { e.printStackTrace(); } } }; IabHelper.OnConsumeFinishedListener mConsumeFinishedListener = new IabHelper.OnConsumeFinishedListener() { @Override public void onConsumeFinished(me.proft.sandbox.utils.billing.Purchase purchase, IabResult result) { Log.d(TAG, "Consumption finished. Purchase: " + purchase + ", result: " + result); // if we were disposed of in the meantime, quit. if (mHelper == null) return; if (result.isSuccess()) { Log.d(TAG, "Consumption successful. Provisioning." + purchase.getSku()); } else { Log.d(TAG, "Error while consuming: " + result); } Log.d(TAG, "End consumption flow."); } }; }
You can get Base64-encoded RSA public key in Google Play Console * -> APP -> Development tools -> Services & APIs*.
Compile and run the application on a physical Android device with Google Play support and click on the "Continue" button. This should cause the Google Play purchase dialog to appear listing the test item.
Testing Google Play Billing
In order to be eligible for test purchases, there are a few steps to go through:
So, to test Google Play Billing, you need to publish your app to an alpha or beta channel in Google Play. After you publish an app to an alpha or beta channel, it can take a few hours for the app to be available for testers.
You can test on any Android-powered hardware device running Android 1.6 or higher. The most current version of the Google Play application must be installed on the device.
It’s easy to set up test purchases — any user account can be chosen to be a test account, and any user of a test account can make test purchases with no charge.
First, upload and publish in-app products that you want testers to be able to purchase. You can upload and publish in-app products in the Play Console. Note that you can upload and publish your in-app items before you publish the APK itself.
Next, create license test accounts for authorized users. In the Developer Console, go to Settings > Account details, then in the License Testing section, add the addresses to Gmail accounts with testing access field.
Once you’ve added the users as license tester accounts and saved the change, within 15 minutes those users can begin making test purchases of your in-app products.
Important. After you publish your app to an alpha or beta channel, your testers need to opt-in to your app’s alpha or beta test using the provided opt-in URL before they can make test purchases. You can see opt-in URL in Developer Console > APP > Release management > App releases > Manage internal test.
Note. License test accounts must be on the user’s Android device. If the device has more than one account, the purchase will be made with the account that downloaded the app. If none of the accounts has downloaded the app, the purchase is made with the first account. Users can confirm the account that is making a purchase by expanding the purchase dialog.
Authorized license test accounts are associated with your developer account in Google Play, rather than with a specific APK or package name. Identifying an account as a test account enables it to purchase any of your in-app products without being charged.
Note. If you want to be able to perform a test purchase on an inapp item more than once, you need to mark the item as consumed after each purchase. To do so, call consumeAsync()
.
Note. Taxes are not computed or assessed for test purchases.
Check list for troubleshooting
If you are getting following error "This version of the application is not configured for billing through Google Play" please check following list.
Prerequisites:
Testing requirements:
Useful links