29 May 2012
Experience building apps for Android with Flash Builder or Flash Professional and Adobe AIR will help you make the most of this article.
Additional required other products
Intermediate
With the In-App Billing Extension for Android from Milkman Games, you can rapidly integrate in-app purchasing into your mobile AIR application using ActionScript 3.
The In-App Billing Extension for Android is a 100 percent native Java solution that enables you to:
Before you can use In-App Billing in your application, you need to set it up properly on the Android Market website.
The next step is to add the com.milkmangames.nativeextensions.AndroidIAB.ane library to your project. (If you are not using Flash Builder 4.6 and later or Flash Professional CS6 and later you'll need to add the AndroidIABAPI.swc library instead.)
In Flash Professional CS6:
In Flash Builder 4.6:
In FlashDevelop:
You can start using the In-App Billing extension with a few simple calls. See example/AndroidIAB.as for a full example that shows how to use the ActionScript API.
Follow these steps to get started:
com.milkmangames.nativeextensions.android.*;
com.milkmangames.nativeextensions.android.events.*;
AndroidIAB.create() . You can check the AndroidIAB.isSupported() method first, to ensure the current platform is Android and not an unsupported platform (like iOS or Windows):if (AndroidIAB.isSupported())
{
AndroidIAB.create();
}
create() has been called, an instance of the AndroidIAB API is available statically by accessing AndroidIAB.androidIAB. Add event listeners for all possible API responses:// billing service ready listeners
AndroidIAB.androidIAB.addEventListener(AndroidBillingEvent.SERVICE_READY,onReady);
AndroidIAB.androidIAB.addEventListener(AndroidBillingEvent.SERVICE_NOT_SUPPORTED,onUnsupported);
// purchase listeners
AndroidIAB.androidIAB.addEventListener(AndroidBillingEvent.PURCHASE_SUCCEEDED,onPurchaseSuccess);
AndroidIAB.androidIAB.addEventListener(AndroidBillingEvent.PURCHASE_REFUNDED,onPurchaseRefunded);
AndroidIAB.androidIAB.addEventListener(AndroidBillingEvent.PURCHASE_CANCELLED,onPurchaseCancelled);
AndroidIAB.androidIAB.addEventListener(AndroidBillingEvent.PURCHASE_USER_CANCELLED,onUserCancelled);
AndroidIAB.androidIAB.addEventListener(AndroidBillingErrorEvent.PURCHASE_FAILED,onPurchaseFailed);
// transaction restore listeners
AndroidIAB.androidIAB.addEventListener(AndroidBillingEvent.TRANSACTIONS_RESTORED,onsRestored);
AndroidIAB.androidIAB.addEventListener(AndroidBillingErrorEvent.TRANSACTION_RESTORE_FAILED,onRestoreF
ailed);
AndroidIAB.androidIAB.startBillingService("yourPublisherPublicKeyHere") method to begin interactions with the Android In-App Billing server. Instructions on obtaining your publisher public key were provided in Setting up your app with your Android Market publishing account. If the current device does not support In-App Billing (because it doesn't have Android Market, for instance), you'll receive the AndroidBillingEvent.SERVICE_NOT_SUPPORTED event. Otherwise, when the service is ready, you'll receive the AndroidBillingEvent.SERVICE_READY event; once that happens, you may begin calling the other API methods to make purchases.AndroidIAB.androidIAB.startBillingService("YOUR_PUBLIC_KEY_HERE");
private function onReady(e:AndroidBillingEvent):void
{
trace("service now ready- you can call purchase and restore methods.");
}
private function onUnsupported(e:AndroidBillingEvent):void
{
trace("sorry, in app billing won't work on this phone!");
}
purchaseItem(itemId) , where itemId is one of the In-App Product IDs you created with your Android Market publishing account:AndroidIAB.androidIAB.purchaseItem("your_itemid");
AndroidBillingEvent.PURCHASE_SUCCEEDED – This event will fire if the purchase went through successfully. The itemId property of the event object will be the In-App Product ID of the item the user just bought.AndroidBillingErrorEvent.PURCHASE_FAILED – This event will fire if an error occurred and the purchase did not go through. The itemId property of the event object will be the In-App Product ID of the item the user just attempted to buy. The errorID property will indicate the specific reason of the error (see Table 1).AndroidBillingEvent.PURCHASE_USER_CANCELLED – This event will fire if the user cancelled the purchase by closing the checkout dialog box or pressing the Back button. The itemId property of the event object will be the In-App Product ID of the item the user just attempted to buy.Table 1. AndroidBillingErrorEvent.errorID values and descriptions
AndroidBillingErrorEvent.errorID Value |
Description |
|
The Internet connection was unavailable. |
|
The connection to the Android Market service was unavailable. |
|
Configuration error (see below). |
|
The |
|
An unknown error occurred. |
If you receive AndroidBillingErrorID.REASON_DEVELOPER_ERROR then there is a problem with your code or configuration. Verify your application descriptor file is set up correctly; see Updating your application descriptor file for details. This error will also be reported if you attempt to purchase an item when the Google account associated with the device is the same as your Registered Developer Email because Google won't let you buy items from yourself. You can avoid this error by switching the Google account associated with the device to a Test Account Email, as described in Setting up your app with your Android Market publishing account.
The Android Billing service works in asynchronously; in other words, events can be dispatched at any time that an item's purchase state changes, even if your application is running in the background. It is up to you as the developer to handle these events, and keep track of what items the user does or does not own.
For instance, it is possible for you to cancel or refund a purchase using the Android Market Developer website. When you do this, your application will receive an event indicating the refund or cancellation (even if it's not in the foreground). When this happens, your app should update its state appropriately, by taking away the item and setting a variable to indicate the item is no longer in the user's possession.
One way you might manage this is to keep a SharedObject instance updated locally, with information about each item that you sell. When you get an AndroidBillingEvent.PURCHASE_SUCCEEDED event, update the SharedObject instance to indicate that the item is now owned. You may also receive a AndroidBillingEvent.PURCHASE_REFUNDED or AndroidBillingEvent.PURCHASE_CANCELLED event. In these cases, you could update your SharedObject instance to indicate that the particular item has been removed.
If you have an unmanaged item, such as a consumable magic spell that can be bought and used multiple times, you are also responsible for keeping track of how many times the item has been bought and used in your application logic.
For a simple example that shows how to manage the full transaction event cycle, see the /example/IABExample.as class in the In-App Billing Extension for Android package.
Any In-App Purchases you marked as managed in the Android Market Developer website are treated as one-time, permanent purchases. This designation is intended for items such as an additional game level or a virtual hat your user gets to keep.
Because these items are managed, Google stores a record of whether the user has purchased them or not. Of course, you still must also maintain your own records of this within your application.
It is possible that the user will uninstall your application from the device, or get a new device and install your application on it. In this situation, you'll need to restore all items the user has previously purchased. To detect if the user has re-installed your app (or possibly just installed it for the first time), you could, for example, keep a variable named firstTimeuse with a default value of true in your SharedObject instance. If firstTimeUse is set, your app can call the restoreManagedTransactions() function, which will replay all the stored managed purchase events for that user. Your app can then listen for the events and update its records to reflect the user's purchases. It would then set firstTimeUse to false so the process is not repeated on the next application start. RestoreManagedTransactions() is not meant to be used every time your application runs, just when it is being run for the first time on a new device.
The following code demonstrates the restoreManagedTransactions() call:
// if the application has not been run since installing, call this
AndroidIAB.androidIAB.restoreManagedTransactions();
After the call is made, one AndroidBillingEvent.PURCHASE_SUCCEEDED event will be fired for each managed item the user has already purchased (if any). The event handler can check the itemId property of the event object, and grant the user the item.
When there are no more items to be restored, an AndroidBillingEvent.TRANSACTIONS_RESTORED event will be dispatched.
If an error occurs with the call, AndroidBillingErrorEvent.TRANSACTION_RESTORE_FAILED will be dispatched instead.
Again, the /example/IABExample.as class in the in the In-App Billing Extension for Android package shows an example of how to manage the full transaction event cycle.
The In-App Billing Extension for Android provides a number of built-in test methods that you can use to ensure you've set up billing correctly. These methods will attempt to contact the billing service, and dispatch the proper events for different fake item use cases, such as a refund or successful purchase. You should make sure these methods work for you before moving on to integrating your real items.
These calls will work whether the Google account associated with your device is a Registered Developer Email or a Test Account Email, as defined earlier. The following examples should be tested separately with event handlers set up to process the results; they are not intended to be called one after the other in succession.
// this will start a purchase dialog and on success callback the PURCHASE_SUCCEEDED event:
AndroidIAB.androidIAB.testPurchaseItemSuccess();
// this will start a purchase dialog then fake a PURCHASE_REFUNDED event
AndroidIAB.androidIAB.testPurchaseItemRefunded();
// this will start a purchase dialog then fake a PURCHASE_CANCELLED event
AndroidIAB.androidIAB.testPurchaseItemCancelled();
// this will start a purchase dialog and fake a PURCHASE_FAILED error event, // with a reason of ITEM_UNAVAILABLE
AndroidIAB.androidIAB.testPurchaseItemUnavailable();
It is also possible to test the purchase flow in an unpublished application using real In-App Purchase IDs, with a few restrictions:
itemId in your code) you are testing must be Published, as described in Setting up your app with your Android Market publishing account. The application itself need not be published, however.AndroidBillingEvent.PURCHASE_CANCELLED or AndroidBillingEvent.PURCHASE_REFUNDED event to fire.
You need to configure your AIR application descriptor file to use the AIR 3.0 SDK (or later), include the In-App Billing extension, and update the Android manifest additions with some Android Billing specific settings. For a working example, see example/app.xml.
<application xmlns="http://ns.adobe.com/air/application/3.0">
<extensions>
<extensionID>com.milkmangames.extensions.AndroidIAB</extensionID>
</extensions>
android.permission.INTERNET and com.android.vending.BILLING permissions must be present for In-App Billing to work. You also must add the com.android.vending.billing.IN_APP_NOTIFY , com.android.vending.billing.RESPONSE_CODE , and com.android.vending.billing.PURCHASE_STATE_CHANGED actions within the <intent-filter> element, as shown below:<android>
<manifestAdditions><![CDATA[
<manifest android:installLocation="auto">
<uses-permission android:name="android.permission.INTERNET"/>
<uses-permission android:name="com.android.vending.BILLING" />
<application>
<service android:name="com.milkmangames.extensions.android.IABBillingService" />
<receiver android:name="com.milkmangames.extensions.android.IABBillingReceiver">
<intent-filter>
<action android:name="com.android.vending.billing.IN_APP_NOTIFY" />
<action android:name="com.android.vending.billing.RESPONSE_CODE" />
<action android:name="com.android.vending.billing.PURCHASE_STATE_CHANGED" />
</intent-filter>
</receiver>
</application>
</manifest>
]]></manifestAdditions>
</android>
If you're using Flash Builder 4.6 or later, or Flash Professional CS6 or later, and have added the In-App Billing for Android extension library as described above, then you can compile as you usually do directly from the IDE. If not and you are building your app with the extension from the command line, then you'll need to specify the directory containing the com.milkmangames.nativeextensions.AndroidIAB.ane file.
Here is an example build command line:
[PATH_TO_AIR_SDK]\bin\adt -package -target apk-debug -storetype pkcs12 -keystore [YOUR_KEYSTORE_FILE]
-storepass [YOUR_PASSWORD] anesample.apk app.xml anesample.swf -extdir [DIRECTORY_CONTAINING_ANE_FILE]
If your app is not receiving events as expected, try these tips:
my_levelpack and an unmanaged one named my_spell . See Setting up your app with your Android Market publishing account for information on how to set up products.Now that you have the In-App Billing Extension for Android up and running, you may want to explore the ActionScript 3 documentation or check out the Game Center, iAd, AdMob or other tools from available from Milkman Games.

This work is licensed under a Creative Commons Attribution-Noncommercial-No Derivative Works 3.0 Unported License.