summaryrefslogtreecommitdiffstats
path: root/docs/html/guide/market/billing/billing_integrate.jd
diff options
context:
space:
mode:
Diffstat (limited to 'docs/html/guide/market/billing/billing_integrate.jd')
-rwxr-xr-xdocs/html/guide/market/billing/billing_integrate.jd198
1 files changed, 140 insertions, 58 deletions
diff --git a/docs/html/guide/market/billing/billing_integrate.jd b/docs/html/guide/market/billing/billing_integrate.jd
index 0cac2eb..d027686 100755
--- a/docs/html/guide/market/billing/billing_integrate.jd
+++ b/docs/html/guide/market/billing/billing_integrate.jd
@@ -3,12 +3,6 @@ parent.title=In-app Billing
parent.link=index.html
@jd:body
-<style type="text/css">
- #jd-content {
- background:transparent url({@docRoot}assets/images/preliminary.png) repeat scroll 0 0;
- }
-</style>
-
<div id="qv-wrapper">
<div id="qv">
<h2>In this document</h2>
@@ -16,7 +10,7 @@ parent.link=index.html
<li><a href="#billing-download">Downloading the Sample Application</a></li>
<li><a href="#billing-add-aidl">Adding the AIDL file to your project</a></li>
<li><a href="#billing-permission">Updating Your Application's Manifest</a></li>
- <li><a href="#billing-service">Creating a Service</a></li>
+ <li><a href="#billing-service">Creating a Service</a></li>
<li><a href="#billing-broadcast-receiver">Creating a BroadcastReceiver</a></li>
<li><a href="#billing-signatures">Creating a security processing component</a></li>
<li><a href="#billing-implement">Modifying Your Application Code</a></li>
@@ -37,10 +31,10 @@ parent.link=index.html
</div>
<div class="special" style="margin-right:345px">
- <p>This documentation provides an early look at the Android Market In-app Billing service. The documentation may change without notice.</p>
+ <p>During the testing phase of the in-app billing release you cannot publish applications that implement in-app billing. You can only upload in-app billing applications as draft applications. For more information, see <a href="{@docRoot}guide/market/billing/billing_about.html">About this Release</a></p>
</div>
-<p>The Android Market In-app Billing service provides a straightforward, simple interface for sending in-app billing requests and managing in-app billing transactions using Android Market. This document helps you implement in-app billing by stepping through the primary implementation tasks, using the in-app billing sample application as an example.</p>
+<p>The Android Market in-app billing service provides a straightforward, simple interface for sending in-app billing requests and managing in-app billing transactions using Android Market. This document helps you implement in-app billing by stepping through the primary implementation tasks, using the in-app billing sample application as an example.</p>
<p>Before you implement in-app billing in your own application, be sure that you read <a href="{@docRoot}guide/market/billing/billing_overview.html">Overview of In-app Billing</a> and <a href="{@docRoot}guide/market/billing/billing_best_practices.html">Security and Design</a>. These documents provide background information that will make it easier for you to implement in-app billing.</p>
@@ -67,7 +61,7 @@ parent.link=index.html
<li>Creating a user interface that lets users select items for purchase.</li>
</ul>
-<p>The sample application includes an application file (<code><code>Dungeons.java</code></code>), the AIDL file for the <code>MarketBillingService</code> (<code>IMarketBillingService.aidl</code>), and several classes that demonstrate in-app billing messaging. It also includes a class that demonstrates basic security tasks, such as signature verification.</p>
+<p>The sample application includes an application file (<code>Dungeons.java</code>), the AIDL file for the <code>MarketBillingService</code> (<code>IMarketBillingService.aidl</code>), and several classes that demonstrate in-app billing messaging. It also includes a class that demonstrates basic security tasks, such as signature verification.</p>
<p>Table 1 lists the source files that are included with the sample application.</p>
<p class="table-caption" id="source-files-table"><strong>Table 1.</strong>
@@ -86,7 +80,7 @@ In-app billing sample application source files.</p>
<tr>
<td>Dungeons.java</td>
-<td>Sample application file that provides a UI for making purchases and diplaying purchase history.</td>
+<td>Sample application file that provides a UI for making purchases and displaying purchase history.</td>
</tr>
<tr>
@@ -130,19 +124,101 @@ In-app billing sample application source files.</p>
</table>
-<p>The in-app billing sample application is available as a downloadable component of the Android SDK. To download the sample application component, launch the Android SDK and AVD Manager and then select the "Market Billing package, revision 1" component (see figure 1), and click <strong>Install Selected</strong> to begin the download.</p>
+<p>The in-app billing sample application is available as a downloadable component of the Android SDK. To download the sample application component, launch the Android SDK and AVD Manager and then select the "Google Market Billing package" component (see figure 1), and click <strong>Install Selected</strong> to begin the download.</p>
<div style="margin-bottom:2em;">
-<img src="{@docRoot}images/billing_package.png" style="text-align:left;margin-bottom:0;" />
-<div style="margin:0 2em;padding:0"><strong>Figure 1.</strong> The Google Market
-Billing package contains the sample application and the AIDL file. </div>
-</div>
+<img src="{@docRoot}images/billing_package.png" height="325" id="figure1" />
+<p class="img-caption">
+ <strong>Figure 1.</strong> The Google Market Billing package contains the sample application and the AIDL file.
+</p>
<p>When the download is complete, the Android SDK and AVD Manager saves the component into the following directory:</p>
<p><code>&lt;sdk&gt;/google-market_billing/</code></p>
+<p>If you want to see an end-to-end demonstration of in-app billing before you integrate in-app billing into your own application, you can build and run the sample application. Building and running the sample application involves three tasks:<p>
+
+<ul>
+ <li>Configuring and building the sample application.</li>
+ <li>Uploading the sample application to Android Market.</li>
+ <li>Setting up test accounts and running the sample application</li>
+</ul>
+
+<p class="note"><strong>Note:</strong> Building and running the sample application is necessary only if you want to see a demonstration of in-app billing. If you do not want to run the sample application, you can skip to the next section, <a href="#billing-add-aidl">Adding the AIDL file to your project</a>.</p>
+
+<h3>Configuring and building the sample application</h3>
+
+<p>Before you can run the sample application, you need to configure it and build it by doing the following:</p>
+
+<ol>
+ <li><strong>Add your Android Market public key to the sample application code.</strong>
+ <p>This enables the application to verify the signature of the transaction information that is returned from Android Market. To add your public key to the sample application code, do the following:</p>
+ <ol>
+ <li>Log in to your Android Market <a href="http://market.android.com/publish">publisher account</a>.</li>
+ <li>On the upper left part of the page, under your name, click <strong>Edit Profile</strong>.</li>
+ <li>On the Edit Profile page, scroll down to the <strong>Licensing &amp; In-app Billing</strong> panel.</li>
+ <li>Copy your public key.</li>
+ <li>Open <code>src/com/example/dungeons/Security.java</code> in the editor of your choice.
+ <p>You can find this file in the sample application's project folder.</p>
+ </li>
+ <li>Add your public key to the following line of code:
+ <p><code>String base64EncodedPublicKey = "your public key here";</code></p>
+ </li>
+ <li>Save the file.</li>
+ </ol>
+ </li>
+ <li><strong>Change the package name of the sample application.</strong>
+ <p>The current package name is <code>com.example.dungeons</code>. Android Market does not let you upload applications with package names that contain <code>com.example</code>, so you must change the package name to something else.</p>
+ </li>
+ <li><strong>Build the sample application in release mode and sign it.</strong>
+ <p>To learn how to build and sign applications, see <a href="{@docRoot}guide/developing/building/index.html">Building and Running</a>.</p>
+ </li>
+</ol>
+
+<h3>Uploading the sample application</h3>
+
+<p>After you build a release version of the sample application and sign it, you need to upload it as a draft to the Android Market publisher site. You also need to create a product list for the in-app items that are available for purchase in the sample application. The following instructions show you how to do this.</p>
+<ol>
+ <li><strong>Upload the release version of the sample application to Android Market.</strong>
+ <p>Do not publish the sample application; leave it as an unpublished draft application. The sample application is for demonstration purposes only and should not be made publicly available on Android Market. To learn how to upload an application to Android Market, see <a href="http://market.android.com/support/bin/answer.py?answer=113469">Uploading applications</a>.</p>
+ </li>
+ <li><strong>Create a product list for the sample application.</strong>
+ <p>The sample application lets you purchase two items: a two-handed sword (<code>sword_001</code>) and a potion (<code>potion_001</code>). We recommend that you set up your product list so that <code>sword_001</code> has a purchase type of "Managed per user account" and <code>potion_001</code> has a purchase type of "Unmanaged" so you can see how these two purchase types behave. To learn how to set up a product list, see <a href="{@docRoot}guide/market/billing/billing_admin.html#billing-list-setup">Creating a Product List</a>.</p>
+ <p class="note"><strong>Note:</strong> You must publish the items in your product list (<code>sword_001</code> and <code>potion_001</code>) even though you are not publishing the sample application. Also, you must have a Google Checkout Merchant account to add items to the sample application's product list.</p>
+ </li>
+</ol>
+
+<h3>Running the sample application</h3>
+
+<p>You cannot run the sample application in the emulator. You must install the sample application onto a device to run it. To run the sample application, do the following:</p>
+
+<ol>
+ <li><strong>Make sure you have at least one test account registered under your Android Market publisher account.</strong>
+ <p>You cannot purchase items from yourself (Google Checkout prohibits this), so you need to create at least one test account that you can use to purchase items in the sample application. To learn how to set up a test account, see <a href="{@docRoot}guide/market/billing/billing_testing.html#billing-testing-setup">Setting up Test Accounts</a>.</p>
+ </li>
+ <li><strong>Verify that your device is running a supported version of the Android Market application or the MyApps application.</strong>
+ <p>If your device is running Android 3.0, in-app billing requires version 5.0.12 (or higher) of the MyApps application. If your device is running any other version of Android, in-app billing requires version 2.3.4 (or higher) of the Android Market application. To learn how to check the version of the Android Market application, see <a href="http://market.android.com/support/bin/answer.py?answer=190860">Updating Android Market</a>.</p>
+ </li>
+ <li><strong>Install the application onto your device.</strong>
+ <p>Even though you uploaded the application to Android Market, the application is not published, so you cannot download it from Android Market to a device. Instead, you must install the application onto your device. To learn how to install an application onto a device, see <a href="{@docRoot}guide/developing/building/building-cmdline.html#RunningOnDevice">Running on a device</a>.</p>
+ </li>
+ <li><strong>Make one of your test accounts the primary account on your device.</strong>
+ <p>The primary account on your device must be one of the <a href="{@docRoot}guide/market/billing/billing_admin.html#billing-testing-setup">test accounts</a> that you registered on the Android Market site. If the primary account on your device is not a test account, you must do a factory reset of the device and then sign in with one of your test accounts. To perform a factory reset, do the following:</p>
+ <ol>
+ <li>Open Settings on your device.</li>
+ <li>Touch <strong>Privacy</strong>.</li>
+ <li>Touch <strong>Factory data reset</strong>.</li>
+ <li>Touch <strong>Reset phone</strong>.</li>
+ <li>After the phone resets, be sure to sign in with one of your test accounts during the device setup process.</li>
+ </ol>
+ </li>
+ <li><strong>Run the application and purchase the sword or the potion.</strong>
+ <p>When you use a test account to purchase items, the test account is billed through Google Checkout and your Google Checkout Merchant account receives a payout for the purchase. Therefore, you may want to refund purchases that are made with test accounts, otherwise the purchases will show up as actual payouts to your merchant account.</p>
+</ol>
+
+<p class="note"><strong>Note</strong>: Debug log messages are turned off by default in the sample application. You can turn them on by setting the variable <code>DEBUG</code> to <code>true</code> in the <code>Consts.java</code> file.</p>
+
<h2 id="billing-add-aidl">Adding the AIDL file to your project</h2>
<p>The sample application contains an Android Interface Definition Language (AIDL) file, which defines the interface to the Android Market in-app billing service <code>MarketBillingService</code>). When you add this file to your project, the Android build environment creates an interface file (<code>IMarketBillingService.java</code>). You can then use this interface to make billing requests by invoking IPC method calls.</p>
@@ -159,15 +235,15 @@ Billing package contains the sample application and the AIDL file. </div>
<li>Build your application.</li>
</ol>
-<p>You should now find a generated interface file named <code><code>IMarketBillingService.java</code></code> in the <code>gen</code> folder of your project.</p>
+<p>You should now find a generated interface file named <code>IMarketBillingService.java</code> in the <code>gen</code> folder of your project.</p>
<h2 id="billing-permission">Updating Your Application's Manifest</h2>
<p>In-app billing relies on the Android Market application, which handles all communication between your application and the Android Market server. To use the Android Market application, your application must request the proper permission. You can do this by adding the <code>com.android.vending.BILLING</code> permission to your AndroidManifest.xml file. If your application does not declare the in-app billing permission, but attempts to send billing requests, Android Market will refuse the requests and respond with a <code>RESULT_DEVELOPER_ERROR</code> response code.</p>
-<p>In addition to the billing permission, you need to declare the {@link android.content.BroadcastReceiver} that you will use to receive asynchronous response messages (broadcast intents) from Android Market, and you need to declare the {@link android.app.Service} that you will use to bind with the <code>IMarketBillingService</code> and send messages to Android Market. You must also declare <a href="{@docRoot}guide/topics/manifest/intent-filter-element.html">intent filters</a> for the {@link android.content.BroadcastReceiver} so that the Android system knows how to handle broadcast intents that are sent from the Android Market application.</p>
+<p>In addition to the billing permission, you need to declare the {@link android.content.BroadcastReceiver} that you will use to receive asynchronous response messages (broadcast intents) from Android Market, and you need to declare the {@link android.app.Service} that you will use to bind with the <code>IMarketBillingService</code> and send messages to Android Market. You must also declare <a href="{@docRoot}guide/topics/manifest/intent-filter-element.html">intent filters</a> for the {@link android.content.BroadcastReceiver} so that the Android system knows how to handle the broadcast intents that are sent from the Android Market application.</p>
-<p>For example, here's how the in-app billing sample application declares the billing permission, the {@link android.content.BroadcastReceiver}, the {@link android.app.Service}, and the intent filters. In the sample application, <code>BillingReceiver</code> is the {@link android.content.BroadcastReceiver} that handles broadcast intents from the Android Market application and <code>BillingService</code> is the {@link android.app.Service} that sends requests to the Android Market application.</p>
+<p>For example, here is how the in-app billing sample application declares the billing permission, the {@link android.content.BroadcastReceiver}, the {@link android.app.Service}, and the intent filters. In the sample application, <code>BillingReceiver</code> is the {@link android.content.BroadcastReceiver} that handles broadcast intents from the Android Market application and <code>BillingService</code> is the {@link android.app.Service} that sends requests to the Android Market application.</p>
<pre>
&lt;?xml version="1.0" encoding="utf-8"?&gt;
@@ -236,7 +312,7 @@ try {
}
</pre>
-<p>After you bind to the service, you need to create a reference to the <code>IMarketBillingService</code> interface so you can make billing requests via IPC method calls. The following code shows you how to do this using the {@link android.content.ServiceConnection#onServiceConnected onServiceConnected()} callback method.</p>
+<p>After you bind to the service, you need to create a reference to the <code>IMarketBillingService</code> interface so you can make billing requests via IPC method calls. The following code shows you how to do this using the {@link android.content.ServiceConnection#onServiceConnected onServiceConnected()} callback method.</p>
<pre>
/**
@@ -265,7 +341,7 @@ try {
<li><code>RESTORE_TRANSACTIONS</code>&mdash;retrieves a user's transaction history for <a href="{@docRoot}guide/market/billing/billing_admin.html#billing-purchase-type">managed purchases</a>.</li>
</ul>
-<p>To make any of these billing requests, you first need to build an initial Bundle that contains the three keys that are required for all requests: <code>BILLING_REQUEST</code>, <code>API_VERSION</code>, and <code>PACKAGE_NAME</code>. The following code sample shows you how to create a helper method named <code>makeRequestBundle()</code> that does this.</p>
+<p>To make any of these billing requests, you first need to build an initial {@link android.os.Bundle} that contains the three keys that are required for all requests: <code>BILLING_REQUEST</code>, <code>API_VERSION</code>, and <code>PACKAGE_NAME</code>. The following code sample shows you how to create a helper method named <code>makeRequestBundle()</code> that does this.</p>
<pre>
protected Bundle makeRequestBundle(String method) {
@@ -296,13 +372,17 @@ protected Bundle makeRequestBundle(String method) {
<p>The <code>makeRequestBundle()</code> method constructs an initial Bundle, which contains the three keys that are required for all requests: <code>BILLING_REQUEST</code>, <code>API_VERSION</code>, and <code>PACKAGE_NAME</code>. The request returns a synchronous {@link android.os.Bundle} response, which contains only a single key: <code>RESPONSE_CODE</code>. The <code>RESPONSE_CODE</code> key can have the following values:</p>
<ul>
<li><code>RESULT_OK</code>&mdash;in-app billing is supported.</li>
- <li><code>RESULT_BILLING_UNAVAILABLE</code>&mdash;in-app billing is not supported or the in-app billing API version you specified is not recognized.</li>
- <li><code>RESULT_ERROR</code>&mdash;there was an error connecting with the Android Market appliction.</li>
- <li><code>RESULT_DEVELOPER_ERROR</code>&mdash;the application is trying to make an in-app billing request but the application has not declared the com.android.vending.BILLING permission in its manifest. Can also indicate that an application is not properly signed, or that you sent a malformed request.</li>
+ <li><code>RESULT_BILLING_UNAVAILABLE</code>&mdash;in-app billing is not available because the in-app billing API version you specified is not recognized or the user is not eligible to make in-app purchases (for example, the user resides in a country that prohibits in-app purchases).</li>
+ <li><code>RESULT_ERROR</code>&mdash;there was an error connecting with the Android Market application.</li>
+ <li><code>RESULT_DEVELOPER_ERROR</code>&mdash;the application is trying to make an in-app billing request but the application has not declared the <code>com.android.vending.BILLING</code> permission in its manifest. Can also indicate that an application is not properly signed, or that you sent a malformed request.</li>
</ul>
<p>The <code>CHECK_BILLING_SUPPORTED</code> request does not trigger any asynchronous responses (broadcast intents).</p>
+<p>We recommend that you invoke the <code>CHECK_BILLING_SUPPORTED</code> request within a <code>RemoteException</code> block. When your code throws a <code>RemoteException</code> it indicates that the remote method call failed, which means that the Android Market application is out of date and needs to be updated. In this case, you can provide users with an error message that contains a link to the <a href="http://market.android.com/support/bin/answer.py?answer=190860">Updating Android Market</a> Help topic.</p>
+
+<p>The sample application demonstrates how you can handle this error condition (see <code>DIALOG_CANNOT_CONNECT_ID</code> in <code>Dungeons.java</code>).</p>
+
<h4>Making a purchase request (REQUEST_PURCHASE)</h4>
<p>To make a purchase request you must do the following:</p>
@@ -336,7 +416,7 @@ protected Bundle makeRequestBundle(String method) {
<h5>Launching the pending intent</h5>
-<p>How you use the pending intent depends on which version of Android a device is running. On Android 1.6, you must use the pending intent to launch the checkout UI in its own separate task instead of your application's activity stack. On Android 2.0 and higher, you can use the pending intent to launch the checkout UI on your application's activity stack. The following code shows you how to do this. You can find this code in the PurchaseObserver.java file in the sample application.</p>
+<p>How you use the pending intent depends on which version of Android a device is running. On Android 1.6, you must use the pending intent to launch the checkout UI in its own separate task instead of your application's activity stack. On Android 2.0 and higher, you can use the pending intent to launch the checkout UI on your application's activity stack. The following code shows you how to do this. You can find this code in the <code>PurchaseObserver.java</code> file in the sample application.</p>
<pre>
void startBuyPageActivity(PendingIntent pendingIntent, Intent intent) {
@@ -369,17 +449,17 @@ void startBuyPageActivity(PendingIntent pendingIntent, Intent intent) {
}
</pre>
-<p class="note">You must launch the pending intent from an activity context and not an application context.</p>
+<p class="caution"><strong>Important:</strong> You must launch the pending intent from an activity context and not an application context. Also, you cannot use the <code>singleTop</code> <a href="{@docRoot}guide/topics/manifest/activity-element.html#lmode">launch mode</a> to launch the pending intent. If you do either of these, the Android system will not attach the pending intent to your application process. Instead, it will bring Android Market to the foreground, disrupting your application.</p>
<h5>Handling broadcast intents</h5>
-<p>A <code>REQUEST_PURCHASE</code> request also triggers two asynchronous responses (broadcast intents). First, the Android Market application sends an <code>ACTION_RESPONSE_CODE</code> broadcast intent, which provides error information about the request. Next, if the request was successful, the Android Market application sends an <code>ACTION_NOTIFY</code> broadcast intent. This message contains a notification ID, which you can use to retrieve the transaction details for the <code>REQUEST_PURCHASE</code> request.</p>
+<p>A <code>REQUEST_PURCHASE</code> request also triggers two asynchronous responses (broadcast intents). First, the Android Market application sends a <code>RESPONSE_CODE</code> broadcast intent, which provides error information about the request. Next, if the request was successful, the Android Market application sends an <code>IN_APP_NOTIFY</code> broadcast intent. This message contains a notification ID, which you can use to retrieve the transaction details for the <code>REQUEST_PURCHASE</code> request.</p>
-<p>Keep in mind, the Android Market application also sends an <code>ACTION_NOTIFY</code> for refunds. For more information, see <a href="{@docRoot}guide/market/billing/billing_overview.html#billing-action-notify">Handling ACTION_NOTIFY messages</a>.</p>
+<p>Keep in mind, the Android Market application also sends an <code>IN_APP_NOTIFY</code> for refunds. For more information, see <a href="{@docRoot}guide/market/billing/billing_overview.html#billing-action-notify">Handling IN_APP_NOTIFY messages</a>.</p>
<h4>Retrieving transaction information for a purchase or refund (GET_PURCHASE_INFORMATION)</h4>
-<p>You retrieve transaction information in response to an <code>ACTION_NOTIFY</code> broadcast intent. The <code>ACTION_NOTIFY</code> message contains a notification ID, which you can use to retrieve transaction information.</p>
+<p>You retrieve transaction information in response to an <code>IN_APP_NOTIFY</code> broadcast intent. The <code>IN_APP_NOTIFY</code> message contains a notification ID, which you can use to retrieve transaction information.</p>
<p>To retrieve transaction information for a purchase or refund you must specify five keys in the request {@link android.os.Bundle}. The following code sample shows how to set these keys and make the request. In the sample, <code>mService</code> is an instance of the <code>MarketBillingService</code> interface.</p>
@@ -394,11 +474,11 @@ void startBuyPageActivity(PendingIntent pendingIntent, Intent intent) {
// Do something with this response.
}
</pre>
-<p>The <code>makeRequestBundle()</code> method constructs an initial Bundle, which contains the three keys that are required for all requests: <code>BILLING_REQUEST</code>, <code>API_VERSION</code>, and <code>PACKAGE_NAME</code>. The additional keys are then added to the bundle prior to invoking the <code>sendBillingRequest()</code> method. The <code>REQUEST_NONCE</code> key contains a cryptographically secure nonce (number used once) that you must generate. The Android Market application returns this nonce with the <code>ACTION_PURCHASE_STATE_CHANGED</code> broadcast intent so you can verify the integrity of the transaction information. The <code>NOTIFY_IDS</code> key contains an array of notification IDs, which you received in the <code>ACTION_NOTIFY</code> broadcast intent.</p>
+<p>The <code>makeRequestBundle()</code> method constructs an initial Bundle, which contains the three keys that are required for all requests: <code>BILLING_REQUEST</code>, <code>API_VERSION</code>, and <code>PACKAGE_NAME</code>. The additional keys are then added to the bundle prior to invoking the <code>sendBillingRequest()</code> method. The <code>REQUEST_NONCE</code> key contains a cryptographically secure nonce (number used once) that you must generate. The Android Market application returns this nonce with the <code>PURCHASE_STATE_CHANGED</code> broadcast intent so you can verify the integrity of the transaction information. The <code>NOTIFY_IDS</code> key contains an array of notification IDs, which you received in the <code>IN_APP_NOTIFY</code> broadcast intent.</p>
<p>The request returns a synchronous {@link android.os.Bundle} response, which contains two keys: <code>RESPONSE_CODE</code> and <code>REQUEST_ID</code>. The <code>RESPONSE_CODE</code> key provides you with the status of the request and the <code>REQUEST_ID</code> key provides you with a unique request identifier for the request.</p>
-<p>A <code>GET_PURCHASE_INFORMATION</code> request also triggers two asynchronous responses (broadcast intents). First, the Android Market application sends an <code>ACTION_RESPONSE_CODE</code> broadcast intent, which provides status and error information about the request. Next, if the request was successful, the Android Market application sends an <code>ACTION_PURCHASE_STATE_CHANGED</code> broadcast intent. This message contains detailed transaction information. The transaction information is contained in a signed JSON string (unencrypted). The message includes the signature so you can verify the integrity of the signed string.</p>
+<p>A <code>GET_PURCHASE_INFORMATION</code> request also triggers two asynchronous responses (broadcast intents). First, the Android Market application sends a <code>RESPONSE_CODE</code> broadcast intent, which provides status and error information about the request. Next, if the request was successful, the Android Market application sends a <code>PURCHASE_STATE_CHANGED</code> broadcast intent. This message contains detailed transaction information. The transaction information is contained in a signed JSON string (unencrypted). The message includes the signature so you can verify the integrity of the signed string.</p>
<h4>Acknowledging transaction information (CONFIRM_NOTIFICATIONS)</h4>
@@ -414,11 +494,13 @@ void startBuyPageActivity(PendingIntent pendingIntent, Intent intent) {
// Do something with this response.
}
</pre>
-<p>The <code>makeRequestBundle()</code> method constructs an initial Bundle, which contains the three keys that are required for all requests: <code>BILLING_REQUEST</code>, <code>API_VERSION</code>, and <code>PACKAGE_NAME</code>. The additional <code>NOTIFY_IDS</code> key is then added to the bundle prior to invoking the <code>sendBillingRequest()</code> method. The <code>NOTIFY_IDS</code> key contains an array of notification IDs, which you received in an <code>ACTION_NOTIFY</code> broadcast intent and also used in a <code>GET_PURCHASE_INFORMATION</code> request.</p>
+<p>The <code>makeRequestBundle()</code> method constructs an initial Bundle, which contains the three keys that are required for all requests: <code>BILLING_REQUEST</code>, <code>API_VERSION</code>, and <code>PACKAGE_NAME</code>. The additional <code>NOTIFY_IDS</code> key is then added to the bundle prior to invoking the <code>sendBillingRequest()</code> method. The <code>NOTIFY_IDS</code> key contains an array of notification IDs, which you received in an <code>IN_APP_NOTIFY</code> broadcast intent and also used in a <code>GET_PURCHASE_INFORMATION</code> request.</p>
<p>The request returns a synchronous {@link android.os.Bundle} response, which contains two keys: <code>RESPONSE_CODE</code> and <code>REQUEST_ID</code>. The <code>RESPONSE_CODE</code> key provides you with the status of the request and the <code>REQUEST_ID</code> key provides you with a unique request identifier for the request.</p>
-<p>A <code>CONFIRM_NOTIFICATIONS</code> request triggers a single asynchronous response&mdash;an <code>ACTION_RESPONSE_CODE</code> broadcast intent. This broadcast intent provides status and error information about the request.</p>
+<p>A <code>CONFIRM_NOTIFICATIONS</code> request triggers a single asynchronous response&mdash;a <code>RESPONSE_CODE</code> broadcast intent. This broadcast intent provides status and error information about the request.</p>
+
+<p class="note"><strong>Note:</strong> As a best practice, you should not send a <code>CONFIRM_NOTIFICATIONS</code> request for a purchased item until you have delivered the item to the user. This way, if your application crashes or something else prevents your application from delivering the product, your application will still receive an <code>IN_APP_NOTIFY</code> broadcast intent from Android Market indicating that you need to deliver the product.</p>
<h4>Restoring transaction information (RESTORE_TRANSACTIONS)</h4>
@@ -434,29 +516,29 @@ void startBuyPageActivity(PendingIntent pendingIntent, Intent intent) {
// Do something with this response.
}
</pre>
-<p>The <code>makeRequestBundle()</code> method constructs an initial Bundle, which contains the three keys that are required for all requests: <code>BILLING_REQUEST</code>, <code>API_VERSION</code>, and <code>PACKAGE_NAME</code>. The additional <code>REQUEST_NONCE</code> key is then added to the bundle prior to invoking the <code>sendBillingRequest()</code> method. The <code>REQUEST_NONCE</code> key contains a cryptographically secure nonce (number used once) that you must generate. The Android Market application returns this nonce with the transactions information contained in the <code>ACTION_PURCHASE_STATE_CHANGED</code> broadcast intent so you can verify the integrity of the transaction information.</p>
+<p>The <code>makeRequestBundle()</code> method constructs an initial Bundle, which contains the three keys that are required for all requests: <code>BILLING_REQUEST</code>, <code>API_VERSION</code>, and <code>PACKAGE_NAME</code>. The additional <code>REQUEST_NONCE</code> key is then added to the bundle prior to invoking the <code>sendBillingRequest()</code> method. The <code>REQUEST_NONCE</code> key contains a cryptographically secure nonce (number used once) that you must generate. The Android Market application returns this nonce with the transactions information contained in the <code>PURCHASE_STATE_CHANGED</code> broadcast intent so you can verify the integrity of the transaction information.</p>
<p>The request returns a synchronous {@link android.os.Bundle} response, which contains two keys: <code>RESPONSE_CODE</code> and <code>REQUEST_ID</code>. The <code>RESPONSE_CODE</code> key provides you with the status of the request and the <code>REQUEST_ID</code> key provides you with a unique request identifier for the request.</p>
-<p>A <code>RESTORE_TRANSACTIONS</code> request also triggers two asynchronous responses (broadcast intents). First, the Android Market application sends an <code>ACTION_RESPONSE_CODE</code> broadcast intent, which provides status and error information about the request. Next, if the request was successful, the Android Market application sends an <code>ACTION_PURCHASE_STATE_CHANGED</code> broadcast intent. This message contains the detailed transaction information. The transaction information is contained in a signed JSON string (unencrypted). The message includes the signature so you can verify the integrity of the signed string.</p>
+<p>A <code>RESTORE_TRANSACTIONS</code> request also triggers two asynchronous responses (broadcast intents). First, the Android Market application sends a <code>RESPONSE_CODE</code> broadcast intent, which provides status and error information about the request. Next, if the request was successful, the Android Market application sends a <code>PURCHASE_STATE_CHANGED</code> broadcast intent. This message contains the detailed transaction information. The transaction information is contained in a signed JSON string (unencrypted). The message includes the signature so you can verify the integrity of the signed string.</p>
<h3>Other service tasks</h3>
-<p>You may also want your {@link android.app.Service} to receive intent messages from your {@link android.content.BroadcastReceiver}. You can use these intent messages to convey the information that was sent asynchronously from the Android Market application to your {@link android.content.BroadcastReceiver}. To see an example of how you can send and receive these intent messages, see the BillingReceiver.java and BillingService.java files in the sample application. You can use these samples as a basis for your own implementation. However, if you use any of the code from the sample application, be sure you follow the guidelines in <a href="{@docRoot}guide/market/billing/billing_best_practices.html">Security and Design</a>.</p>
+<p>You may also want your {@link android.app.Service} to receive intent messages from your {@link android.content.BroadcastReceiver}. You can use these intent messages to convey the information that was sent asynchronously from the Android Market application to your {@link android.content.BroadcastReceiver}. To see an example of how you can send and receive these intent messages, see the <code>BillingReceiver.java</code> and <code>BillingService.java</code> files in the sample application. You can use these samples as a basis for your own implementation. However, if you use any of the code from the sample application, be sure you follow the guidelines in <a href="{@docRoot}guide/market/billing/billing_best_practices.html">Security and Design</a>.</p>
<h2 id="billing-broadcast-receiver">Creating a BroadcastReceiver</h2>
<p>The Android Market application uses broadcast intents to send asynchronous billing responses to your application. To receive these intent messages, you need to create a {@link android.content.BroadcastReceiver} that can handle the following intents:</p>
<ul>
- <li>ACTION_RESPONSE_CODE
+ <li>com.android.vending.billing.RESPONSE_CODE
<p>This broadcast intent contains an Android Market response code, and is sent after you make an in-app billing request. For more information about the response codes that are sent with this response, see <a href="{@docRoot}guide/market/billing/billing_reference.html#billing-codes">Android Market Response Codes for In-app Billing</a>.</p>
</li>
- <li>ACTION_NOTIFY
+ <li>com.android.vending.billing.IN_APP_NOTIFY
<p>This response indicates that a purchase has changed state, which means a purchase succeeded, was canceled, or was refunded. For more information about notification messages, see <a href="{@docRoot}guide/market/billing/billing_reference.html#billing-intents">In-app Billing Broadcast Intents</a></p>
</li>
- <li>ACTION_PURCHASE_STATE_CHANGED
+ <li>com.android.vending.billing.PURCHASE_STATE_CHANGED
<p>This broadcast intent contains detailed information about one or more transactions. For more information about purchase state messages, see <a href="{@docRoot}guide/market/billing/billing_reference.html#billing-intents">In-app Billing Broadcast Intents</a></p>
</li>
</ul>
@@ -473,28 +555,28 @@ void startBuyPageActivity(PendingIntent pendingIntent, Intent intent) {
<th>Description</th>
</tr>
<tr>
- <td><code>ACTION_RESPONSE_CODE</code></td>
- <td><code>INAPP_REQUEST_ID</code></td>
+ <td><code>com.android.vending.billing.RESPONSE_CODE</code></td>
+ <td><code>request_id</code></td>
<td>A <code>long</code> representing a request ID. A request ID identifies a specific billing request and is returned by Android Market at the time a request is made.</td>
</tr>
<tr>
- <td><code>ACTION_RESPONSE_CODE</code></td>
- <td><code>INAPP_RESPONSE_CODE</code></td>
+ <td><code>com.android.vending.billing.RESPONSE_CODE</code></td>
+ <td><code>response_code</code></td>
<td>An <code>int</code> representing the actual Android Market server response code.</td>
</tr>
<tr>
- <td><code>ACTION_NOTIFY</code></td>
- <td><code>NOTIFICATION_ID</code></td>
+ <td><code>com.android.vending.billing.IN_APP_NOTIFY</code></td>
+ <td><code>notification_id</code></td>
<td>A <code>String</code> representing the notification ID for a given purchase state change. Android Market notifies you when there is a purchase state change and the notification includes a unique notification ID. To get the details of the purchase state change, you send the notification ID with the <code>GET_PURCHASE_INFORMATION</code> request.</td>
</tr>
<tr>
- <td><code>ACTION_PURCHASE_STATE_CHANGED</code></td>
- <td><code>INAPP_SIGNED_DATA</code></td>
+ <td><code>com.android.vending.billing.PURCHASE_STATE_CHANGED</code></td>
+ <td><code>inapp_signed_data</code></td>
<td>A <code>String</code> representing the signed JSON string. The JSON string contains information about the billing transaction, such as order number, amount, and the item that was purchased or refunded.</td>
</tr>
<tr>
- <td><code>ACTION_PURCHASE_STATE_CHANGED</code></td>
- <td><code>INAPP_SIGNATURE</code></td>
+ <td><code>com.android.vending.billing.PURCHASE_STATE_CHANGED</code></td>
+ <td><code>inapp_signature</code></td>
<td>A <code>String</code> representing the signature of the JSON string.</td>
</tr>
</table>
@@ -547,17 +629,17 @@ public class BillingReceiver extends BroadcastReceiver {
}
</pre>
-<p>In addition to receiving broadcast intents from the Android Market application, your {@link android.content.BroadcastReceiver} must handle the information it received in the broadcast intents. Usually, your {@link android.content.BroadcastReceiver} does this by sending the information to a local service (discussed in the next section). The BillingReceiver.java file in the sample application shows you how to do this. You can use this sample as a basis for your own {@link android.content.BroadcastReceiver}. However, if you use any of the code from the sample application, be sure you follow the guidelines that are discussed in <a href="{@docRoot}guide/market/billing/billing_best_practices.html">Security and Design </a>.</p>
+<p>In addition to receiving broadcast intents from the Android Market application, your {@link android.content.BroadcastReceiver} must handle the information it received in the broadcast intents. Usually, your {@link android.content.BroadcastReceiver} does this by sending the information to a local service (discussed in the next section). The <code>BillingReceiver.java</code> file in the sample application shows you how to do this. You can use this sample as a basis for your own {@link android.content.BroadcastReceiver}. However, if you use any of the code from the sample application, be sure you follow the guidelines that are discussed in <a href="{@docRoot}guide/market/billing/billing_best_practices.html">Security and Design </a>.</p>
<h2 id="billing-signatures">Verifying Signatures and Nonces</h2>
-<p>The in-app billing service uses two mechanisms to help verify the integrity of the transaction information you receive from Android Market: nonces and signatures. A nonce (number used once) is a cryptographically secure number that your application generates and sends with every <code>GET_PURCHASE_INFORMATION</code> and <code>RESTORE_TRANSACTIONS</code> request. The nonce is returned with the <code>ACTION_PURCHASE_STATE_CHANGED</code> broadcast intent, enabling you to verify that any given <code>ACTION_PURCHASE_STATE_CHANGED</code> response corresponds to an actual request that you made. Every <code>ACTION_PURCHASE_STATE_CHANGED</code> broadcast intent also includes a signed JSON string and a signature, which you can use to verify the integrity of the response.</p>
+<p>The in-app billing service uses two mechanisms to help verify the integrity of the transaction information you receive from Android Market: nonces and signatures. A nonce (number used once) is a cryptographically secure number that your application generates and sends with every <code>GET_PURCHASE_INFORMATION</code> and <code>RESTORE_TRANSACTIONS</code> request. The nonce is returned with the <code>PURCHASE_STATE_CHANGED</code> broadcast intent, enabling you to verify that any given <code>PURCHASE_STATE_CHANGED</code> response corresponds to an actual request that you made. Every <code>PURCHASE_STATE_CHANGED</code> broadcast intent also includes a signed JSON string and a signature, which you can use to verify the integrity of the response.</p>
<p>Your application must provide a way to generate, manage, and verify nonces. The following sample code shows some simple methods you can use to do this.</p>
<pre>
private static final SecureRandom RANDOM = new SecureRandom();
- private static HashSet&lt;Long&gt; sKnownNonces = new HashSet&lt;Long&gt;();
+ private static HashSet&lt;Long&gt; sKnownNonces = new HashSet&lt;Long&gt;();
public static long generateNonce() {
long nonce = RANDOM.nextLong();
@@ -574,7 +656,7 @@ public class BillingReceiver extends BroadcastReceiver {
}
</pre>
-<p>Your application must also provide a way to verify the signatures that accompany every <code>ACTION_PURCHASE_STATE_CHANGED</code> broadcast intent. The Security.java file in the sample application shows you how to do this. If you use this file as a basis for your own security implementation, be sure to follow the guidelines in <a href="{@docRoot}guide/market/billing/billing_best_practices.html">Security and Design</a> and obfuscate your code.</p>
+<p>Your application must also provide a way to verify the signatures that accompany every <code>PURCHASE_STATE_CHANGED</code> broadcast intent. The <code>Security.java</code> file in the sample application shows you how to do this. If you use this file as a basis for your own security implementation, be sure to follow the guidelines in <a href="{@docRoot}guide/market/billing/billing_best_practices.html">Security and Design</a> and obfuscate your code.</p>
<p>You will need to use your Android Market public key to perform the signature verification. The following procedure shows you how to retrieve Base64-encoded public key from the Android Market publisher site.</p>
@@ -582,17 +664,17 @@ public class BillingReceiver extends BroadcastReceiver {
<li>Log in to your <a href="http://market.android.com/publish">publisher account</a>.</li>
<li>On the upper left part of the page, under your name, click <strong>Edit profile</strong>.</li>
<li>On the Edit Profile page, scroll down to the Licensing &amp; In-app Billing panel (see figure 2).</li>
- <li>Copy your public key to the clipboard.</li>
+ <li>Copy your public key.</li>
</ol>
<p class="caution"><strong>Important</strong>: To keep your public key safe from malicious users and hackers, do not embed your public key as an entire literal string. Instead, construct the string at runtime from pieces or use bit manipulation (for example, XOR with some other string) to hide the actual key. The key itself is not secret information, but you do not want to make it easy for a hacker or malicious user to replace the public key with another key.</p>
<div style="margin-bottom:2em;">
-<img src="{@docRoot}images/billing_public_key.png" style="text-align:left;margin-bottom:0;" />
-<div style="margin:0 2em;padding:0"><strong>Figure 2.</strong> The Licensing and In-app Billing
-panel of your account's Edit Profile page lets you see your public key.</div>
-</div>
+<img src="{@docRoot}images/billing_public_key.png" height="510" id="figure2" />
+<p class="img-caption">
+ <strong>Figure 2.</strong> The Licensing and In-app Billing panel of your account's Edit Profile page lets you see your public key.
+</p>
<h2 id="billing-implement">Modifying Your Application Code</h2>