アプリ内課金広告

アプリ内課金(IAP)広告を掲載すると、ユーザーがアプリ内で直接購入操作を行えるようになります。

このガイドでは、IAP 広告をインタースティシャル スロットに提供するために、アプリで行う必要のあるコード変更について説明します。Google Play アカウントや AdMob アカウントで購入商品を設定する方法など、その他に必要なステップについては、このガイドでは説明しません。

その他の情報については、アプリ内課金向け(IAP)自社広告の導入ガイド をご覧ください。

前提条件

InAppPurchaseActivity と支払い許可を AndroidManifest.xml に追加する

IAP 広告では、AndroidManifest.xmlActivity を追加する必要があります。

<activity android:name="com.google.android.gms.ads.purchase.InAppPurchaseActivity"
          android:theme="@style/Theme.IAPTheme"/>

さらに、次のような com.android.vending.BILLING 許可も追加します。

<uses-permission android:name="com.android.vending.BILLING" />

PlayStorePurchaseListener と InAppPurchaseListener の比較

IAP 広告をアプリに実装する方法は 2 種類あります。

初級者には PlayStorePurchaseListener の使用をおすすめします。PlayStorePurchaseListener を使用すれば Google Play 課金フロー全体が Mobile Ads SDK に実装されるため、必要な操作は、ユーザーが購入した商品のクレジット処理のみです。ただし、PlayStorePurchaseListener は、消耗品にのみ使用できるという制限があります。

InAppPurchaseListener の実装は、アプリ内課金を実装済みのデベロッパーに推奨されます。InAppPurchaseListener を使用した場合、Mobile Ads SDK は、ユーザーが特定の商品の購入に興味を持っていることの通知のみを行います。 アプリ内課金処理を完了して結果を Mobile Ads SDK に報告するかどうかはデベロッパーが自由に決めることができます。InAppPurchaseListener を実装する利点は、IAP 広告を消耗品にも消耗品以外にも実装できるという点です。ただし、アプリ内課金をまだ実装していない場合は、新しいコードを多数作成することが必要になります。

PlayStorePurchaseListener

IAP 広告を配信するには、PlayStorePurchaseListener を実装する必要があります。

public interface PlayStorePurchaseListener {
    boolean isValidPurchase(String productId);
    void onInAppPurchaseFinished(InAppPurchaseResult inAppPurchaseResult);
}

isValidPurchase

isValidPurchase メソッドを利用すれば、このアイテムの購入が有効かどうかを確認できます。ここで false が返されると購入操作がキャンセルされます。

@Override
public boolean isValidPurchase(String sku) {
  // Optional: check if the product has already been purchased.
  try {
    if (getOwnedProducts().contains(sku)) {
      // Handle the case if product is already purchased.
      return false;
    }
  } catch (RemoteException e) {
    return false;
  }
  return true;
}

onInAppPurchaseFinished

onInAppPurchaseFinished メソッドは、ユーザーが購入を完了したときに呼び出されます。このメソッドでは、ユーザーの入金を記録し、商品を消化するために InAppPurchaseResult.finishPurchase() を呼び出す必要があります。

@Override
public void onInAppPurchaseFinished(InAppPurchaseResult result) {
  int resultCode = result.getResultCode();
  if (resultCode == Activity.RESULT_OK) {
    // Credit the user with goods.

    // Call finishPurchase() to consume the product.
    result.finishPurchase();
  }
}

インタースティシャルへの PlayStorePurchaseListener の登録

インタースティシャル広告を作成するとき、InterstitialAd.setPlayStorePurchaseParams を呼び出してインタースティシャル広告に PlayStorePurchaseListener を登録する必要があります。setPlayStorePurchaseParams メソッドも、オプションの検証用に Android アプリの公開鍵を受け取ります。

PlayStorePurchaseListener の設定例を次に示します。

interstitialAd = new InterstitialAd(this);
private String base64PublicKey = "MIIBIjANBgkqhkiG ... "; // truncated for this example
// Assumes "this" activity implemented PlayStorePurchaseListener.
interstitialAd.setPlayStorePurchaseParams(this, base64PublicKey);

サンプルコードの全文

サンプルコードの全文は以下のボタンをクリックしてダウンロードできます。

サンプルをダウンロード

MainActivity.java

package admob.demo.iap.defaultpurchase;

import com.google.android.gms.ads.AdListener;
import com.google.android.gms.ads.AdRequest;
import com.google.android.gms.ads.InterstitialAd;
import com.google.android.gms.ads.purchase.InAppPurchaseResult;
import com.google.android.gms.ads.purchase.PlayStorePurchaseListener;

import android.app.Activity;
import android.os.Bundle;
import android.os.RemoteException;
import android.util.Log;
import android.view.View;
import android.widget.Button;

import com.android.vending.billing.IInAppBillingService;

import java.util.Collections;
import java.util.List;

public class MainActivity extends Activity implements PlayStorePurchaseListener {

  public static final int BILLING_RESPONSE_RESULT_OK = 0;

  private InterstitialAd interstitial;
  private IInAppBillingService mService;
  private Button showAdButton;

  @Override
  protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);
    showAdButton = (Button) findViewById(R.id.showAd);
    showAdButton.setEnabled(false);

    // Create the interstitial ad and set Google Play store purchase parameters.
    interstitial = new InterstitialAd(this);
    // No need to set a public key for IAP ads.
    interstitial.setPlayStorePurchaseParams(this, null);

    // Put your ad unit ID here, e.g., "ca-app-pub-2412876219430673/4729615340"
    interstitial.setAdUnitId();

    setInterstitialAdListener();
  }

  private void setInterstitialAdListener() {
    // Set an AdListener.
    interstitial.setAdListener(new AdListener() {
      @Override
      public void onAdLoaded() {
        showAdButton.setEnabled(true);
      }

      @Override
      public void onAdClosed() {
        showAdButton.setEnabled(false);
        // Optional: your custom code here.
      }
    });
  }

  public void loadInterstitial(View v) {
    // Create ad request.
    AdRequest adRequest = new AdRequest.Builder().build();

    // Begin loading interstitial ad.
    interstitial.loadAd(adRequest);
  }

  public void displayInterstitial(View v) {
    if (interstitial.isLoaded()) {
      interstitial.show();
    }
  }

  @Override
  public boolean isValidPurchase(String sku) {
    // Optional: check if the product has already been purchased.
    try {
      if (getOwnedProducts().contains(sku)) {
        // Handle the case if product is already purchased.
        return false;
      }
    } catch (RemoteException e) {
      Log.e("Iap-Ad", "Query purchased product failed.", e);
      return false;
    }
    return true;
  }

  @Override
  public void onInAppPurchaseFinished(InAppPurchaseResult result) {
    Log.i("Iap-Ad", "onInAppPurchaseFinished Start");
    int resultCode = result.getResultCode();
    Log.i("Iap-Ad", "result code: " + resultCode);
    String sku = result.getProductId();
    if (resultCode == Activity.RESULT_OK) {
      Log.i("Iap-Ad", "purchased product id: " + sku);
      int responseCode = result.getPurchaseData().getIntExtra(
          "RESPONSE_CODE", BILLING_RESPONSE_RESULT_OK);
      String purchaseData = result.getPurchaseData().getStringExtra("INAPP_PURCHASE_DATA");
      Log.i("Iap-Ad", "response code: " + responseCode);
      Log.i("Iap-Ad", "purchase data: " + purchaseData);

      // Finish purchase and consume product.
      result.finishPurchase();
      // if (responseCode == BILLING_RESPONSE_RESULT_OK) {
      // Optional: your custom process goes here, e.g., add coins after purchase.
      //  }
    } else {
      Log.w("Iap-Ad", "Failed to purchase product: " + sku);
    }
    Log.i("Iap-Ad", "onInAppPurchaseFinished End");
  }

  private List getOwnedProducts() throws RemoteException {
    // Query for purchased items.
    // See http://developer.android.com/google/play/billing/billing_reference.html and
    // http://developer.android.com/google/play/billing/billing_integrate.html
    Bundle ownedItems = mService.getPurchases(3, getPackageName(), "inapp", null);
    int response = ownedItems.getInt("RESPONSE_CODE");
    Log.i("Iap-Ad", "Response code of purchased item query");
    if (response == 0) {
      return ownedItems.getStringArrayList("INAPP_PURCHASE_ITEM_LIST");
    }
    return Collections.emptyList();
  }
}

activity_main.xml

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
                xmlns:tools="http://schemas.android.com/tools"
                android:layout_width="match_parent"
                android:layout_height="match_parent"
                android:paddingBottom="@dimen/activity_vertical_margin"
                android:paddingLeft="@dimen/activity_horizontal_margin"
                android:paddingRight="@dimen/activity_horizontal_margin"
                android:paddingTop="@dimen/activity_vertical_margin"
                tools:context=".MainActivity" >
    <Button android:id="@+id/loadAd"
            android:layout_height="wrap_content"
            android:layout_width="wrap_content"
            android:onClick="loadInterstitial"
            android:text="LoadAds" />
    <Button android:id="@+id/showAd"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_alignBaseline="@+id/loadAd"
            android:layout_alignBottom="@+id/loadAd"
            android:layout_centerHorizontal="true"
            android:onClick="displayInterstitial"
            android:text="ShowAds" />
</RelativeLayout>

AndroidManifest.xml

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="admob.demo.iap.defaultpurchase"
    android:versionCode="2"
    android:versionName="0.2" >

    <uses-sdk
        android:minSdkVersion="8"
        android:targetSdkVersion="19" />

    <uses-permission android:name="android.permission.INTERNET" />
    <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
    <uses-permission android:name="com.android.vending.BILLING" />

    <application
        android:allowBackup="true"
        android:icon="@drawable/ic_launcher"
        android:label="@string/app_name"
        android:theme="@style/AppTheme" >
        <meta-data
            android:name="com.google.android.gms.version"
            android:value="@integer/google_play_services_version" />
        <activity
            android:name="admob.demo.iap.defaultpurchase.MainActivity"
            android:label="@string/app_name" >
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />
                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
        <activity
            android:name="com.google.android.gms.ads.purchase.InAppPurchaseActivity"
            android:theme="@style/Theme.IAPTheme" />
        <activity
            android:name="com.google.android.gms.ads.AdActivity"
            android:configChanges="keyboard|keyboardHidden|orientation|screenLayout|uiMode|screenSize|smallestScreenSize" />
    </application>
</manifest>

InAppPurchaseListener

IAP 広告を配信するために、InAppPurchaseListener を実装する必要があります。

public interface InAppPurchaseListener {
    void onInAppPurchaseRequested(InAppPurchase inAppPurchase);
}

このインターフェースには、onInAppPurchaseRequested という 1 つのメソッドが含まれており、ユーザーが商品を購入する意思を示したとき呼び出されます。この呼び出しを受け取ったアプリは、アプリ内課金フローを開始します。ユーザーがどの商品に購入の意思を示したのかを見るには、InAppPurchase.getProductId を確認します。

解決の記録

購入フローが完了したら、購入の結果を記録する必要があります。

使用可能な解決は次のとおりです。

インタースティシャルへの InAppPurchaseListener の登録

InAppPurchaseListener を実装したら、インタースティシャルに設定して IAP 広告を利用できるようにする必要があります。

interstitialAd = new InterstitialAd(this);
// Assumes "this" activity implemented InAppPurchaseListener.
interstitialAd.setInAppPurchaseListener(this);

フィードバックを送信...