このトピックでは、Android インターフェース定義言語(AIDL)を使用する請求の統合から移行する方法について説明します。AIDL を使用した Google Play の課金システムへのアクセスはサポートが終了しているため、今後はすべての統合で Google Play Billing Library を使用する必要があります。
移行手順
Google Play 請求サービス ライブラリをインポートする
まず、Google Play 請求サービス ライブラリに依存関係を追加します。Gradle を使用している場合は、アプリの build.gradle
ファイルに次のコードを追加できます。
Groovy
dependencies { def billing_version = "6.0.0" implementation "com.android.billingclient:billing:$billing_version" }
Kotlin
dependencies { val billing_version = "6.0.0" implementation("com.android.billingclient:billing:$billing_version") }
以前の参照コードからコピーした可能性がある「グルー」コード(IabHelper
など)はすべて削除できます。IabHelper
が提供する機能は現在、Google Play 請求サービス ライブラリに含まれています。
com.android.vending.BILLING
権限を削除する
com.android.vending.BILLING
権限は Google Play 請求サービス ライブラリのマニフェスト内に埋め込まれています。この権限をアプリのマニフェスト内で明示的に追加する必要はなくなりました。
Google Play 請求サービスに接続する
Google Play Billing Library のメソッド BillingClient
は接続の管理を行います。移行する場合、アプリを次のように変更します。
BillingClient
のインスタンスを作成します。BillingClientStateListener
を実装し、サービスのステータスに関するコールバックを受け取ります。BillingClient
インスタンスでstartConnection()
を呼び出します。- アプリ内購入に関連する
onActivityResult()
のコードを削除してPurchasesUpdatedListener
に移動します。
次の例は、アプリの変更前と変更後のコードを示しています。
変更前
mServiceConn = new ServiceConnection() {
@Override
public void onServiceDisconnected(ComponentName name) {
...
}
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
...
}
};
Intent serviceIntent = new Intent("com.android.vending.billing.InAppBillingService.BIND");
serviceIntent.setPackage("com.android.vending");
List<ResolveInfo> intentServices = mContext.getPackageManager()
.queryIntentServices(serviceIntent, 0);
if (intentServices != null && !intentServices.isEmpty()) {
mContext.bindService(serviceIntent, mServiceConn, Context.BIND_AUTO_CREATE);
} else {
// Handle errors.
...
}
...
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
IabResult result;
if (requestCode != mRequestCode || data == null) {
// Handle errors.
...
}
int responseCode = getResponseCodeFromIntent(data);
String purchaseData = data.getStringExtra(RESPONSE_INAPP_PURCHASE_DATA);
String dataSignature = data.getStringExtra(RESPONSE_INAPP_SIGNATURE);
if (resultCode != Activity.RESULT_OK || responseCode != BILLING_RESPONSE_RESULT_OK) {
// Handle errors.
...
}
// Process successful purchase.
...
return true;
}
変更後
Kotlin
class MyBillingImpl(private var billingClient: BillingClient) : PurchasesUpdatedListener { init { billingClient = BillingClient.newBuilder(activity).setListener(this).build() billingClient.startConnection(object : BillingClientStateListener { override fun onBillingSetupFinished(billingResult: BillingResult?) { // Logic from ServiceConnection.onServiceConnected should be moved here. } override fun onBillingServiceDisconnected() { // Logic from ServiceConnection.onServiceDisconnected should be moved here. } }) } override fun onPurchasesUpdated( billingResult: BillingResult?, purchases: MutableList<Purchase>? ) { // Logic from onActivityResult should be moved here. } }
Java
public class MyBillingImpl implements PurchasesUpdatedListener { private BillingClient billingClient; ... public void initialize() { billingClient = BillingClient.newBuilder(activity).setListener(this).build(); billingClient.startConnection(new BillingClientStateListener() { @Override public void onBillingSetupFinished(BillingResult billingResult) { // Logic from ServiceConnection.onServiceConnected should be moved here. } @Override public void onBillingServiceDisconnected() { // Logic from ServiceConnection.onServiceDisconnected should be moved here. } }); } @Override public void onPurchasesUpdated( @BillingResponse int responseCode, @Nullable List<Purchase> purchases) { // Logic from onActivityResult should be moved here. } }
購入する
購入ダイアログを起動する方法は次のとおりです。
- SKU の詳細の
Bundle
をSkuDetailsParams
に変換します。 mService.getSkuDetails()
の呼び出しを、BillingClient.querySkuDetailsAsync()
を使用するように切り替えます。- 購入インテントの
Bundle
をBillingFlowParams
オブジェクトに変換します。 mService.getBuyIntent()
の呼び出しを、BillingClient.launchBillingFlow()
を使用するように切り替えます。- アプリ内購入に関連するコードを
onActivityResult()
から削除し、そのコードをPurchasesUpdatedListener
に移動します。
次の例は、アプリの変更前と変更後のコードを示しています。
変更前
// Query Skus
String skuToSell = "premium_upgrade";
ArrayList<String> skus = new Arraylist<>();
skus.add(skuToSell);
Bundle querySkus = new Bundle();
querySkus.putStringArrayList(GET_SKU_DETAILS_ITEM_LIST, skus);
Bundle skuDetails = mService.getSkuDetails(3,
mContext.getPackageName(),
itemType,
querySkus);
if (!skuDetails.containsKey(RESPONSE_GET_SKU_DETAILS_LIST)) {
// Handle errors.
...
}
// Launch Buy Flow
Bundle buyIntentBundle = mService.getBuyIntent(3,
mContext.getPackageName(),
skuToSell,
"Inapp",
"");
int response = getResponseCodeFromBundle(buyIntentBundle);
if (response != BILLING_RESPONSE_RESULT_OK) {
// Handle errors.
...
}
PendingIntent pendingIntent = buyIntentBundle.getParcelable(RESPONSE_BUY_INTENT);
act.startIntentSenderForResult(pendingIntent.getIntentSender(),
requestCode,
new Intent(),
Integer.valueOf(0),
Integer.valueOf(0),
Integer.valueOf(0));
// Purchase is handled in onActivityResult illustrated in the previous section.
変更後
Kotlin
val skuToSell = "premium_upgrade" val skuList = mutableListOf<String>() skuList.add(skuToSell) val params = SkuDetailsParams.newBuilder() params.setSkusList(skuList).setType(BillingClient.SkuType.INAPP) billingClient.querySkuDetailsAsync(params.build(), object : SkuDetailsResponseListener { override fun onSkuDetailsResponse( billingResult: BillingResult?, skuDetailsList: MutableList<SkuDetails>?) { // Process the result. } }) // SkuDetails object obtained above. val skuDetails = ... val purchaseParams = BillingFlowParams.newBuilder() .setSkuDetails(skuDetails) .build() billingClient.launchBillingFlow(activity, purchaseParams) // Purchase is handled in onPurchasesUpdated illustrated in the previous section
Java
String skuToSell = "premium_upgrade"; List<String> skuList = new ArrayList<> (); skuList.add(skuToSell); SkuDetailsParams.Builder params = SkuDetailsParams.newBuilder(); params.setSkusList(skuList).setType(SkuType.INAPP); billingClient.querySkuDetailsAsync(params.build(), new SkuDetailsResponseListener() { @Override public void onSkuDetailsResponse(BillingResult billingResult, List<SkuDetails> skuDetailsList) { // Process the result. ... } }); // SkuDetails object obtained above. SkuDetails skuDetails = ...; BillingFlowParams purchaseParams = BillingFlowParams.newBuilder() .setSkuDetails(skuDetails) .build(); mBillingClient.launchBillingFlow(mActivity, purchaseParams); // Purchase is handled in onPurchasesUpdated illustrated in the previous section.
購入アイテムを消費する
Google Play 請求サービス ライブラリを使用して購入アイテムを消費する方法は次のとおりです。
consumePurchase()
ではなくBillingClient.consumeAsync()
を呼び出します。ConsumeResponseListener
を実装します。
次の例は、アプリの変更前と変更後のコードを示しています。
変更前
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
int responseCode = data.getIntExtra(RESPONSE_CODE);
JSONObject purchaseData =
new JSONObject(data.getStringExtra("INAPP_PURCHASE_DATA"));
String token = purchaseData.get("purchaseToken");
...
// Consume purchase
int response = mService.consumePurchase(3, mContext.getPackageName(), token);
if (response != BILLING_RESPONSE_RESULT_OK) {
// Handle errors.
...
}
// Handle successful consumption.
}
変更後
Kotlin
class MyBillingImpl(private val billingClient: BillingClient) : ... , ConsumeResponseListener { fun consumePurchase(purchaseToken: String) { val consumeParams = ConsumeParams .newBuilder() .setPurchaseToken(purchaseToken) .build() } override fun onConsumeResponse( billingResult: BillingResult?, purchaseToken: String?) { // Handle consumption } }
Java
public class MyBillingImpl implements ..., ConsumeResponseListener { private BillingClient billingClient; ... public void consumePurchase(String purchaseToken) { ConsumeParams consumeParams = ConsumeParams.newBuilder() .setPurchaseToken(purchaseToken) .build(); } @Override void onConsumeResponse(BillingResult billingResult, String purchaseToken) { // Handle consumption. ... } }
購入を承認する
Google Play 請求サービス ライブラリのバージョン 2.0 以降では、アプリですべての購入アイテムを消費するか、すべての購入を承認する必要があります。
3 日以内に購入アイテムを消費するか、購入を承認しないと、Google が自動的に購入を取り消し、ユーザーに払い戻しを行います。詳しくは、購入を承認するをご覧ください。
アプリ外購入を認識する
アプリ外購入の処理を Google Play 請求サービス ライブラリに移行する方法は次のとおりです。
- アプリが
BillingClient.queryPurchasesAsync()
の呼び出しをアプリのonResume()
コールバックで行っていることを確認します。 com.android.vending.billing.PURCHASES_UPDATED
のブロードキャスト レシーバを削除し、対応するコールバックのコードをPurchasesUpdatedListener
に移動します。
以前は、Google Play 請求サービスを AIDL と統合する場合、アプリ外購入を処理するには、アプリで com.android.vending.billing.PURCHASES_UPDATED
インテントを受け取るリスナーを登録する必要がありました。
アプリが実行されていない間に行われたすべての購入が認識されるようにするには、最初のステップとして、Google Play Billing Library を使用して、queryPurchasesAsync()
をアプリの onResume()
コールバックで呼び出す必要があります。アプリが実行中の間は、Google Play Billing Library がアプリ外購入を自動的にリッスンし、PurchasesUpdatedListener
を介して通知します。
保留中のトランザクションを処理する
Google Play 請求サービス ライブラリのバージョン 2.0 以降では、購入してから利用権を付与するまでの間に追加の操作が必要な保留中のトランザクションをアプリで処理する必要があります。たとえば、ユーザーが実店舗でアプリ内アイテムを現金で購入するようなケースがあります。その場合は、トランザクションがアプリの外部で完了することになります。このようなシナリオでは、ユーザーがトランザクションを完了した後にのみ利用権を付与する必要があります。
詳しくは、保留中のトランザクションをサポートするをご覧ください。
デベロッパー ペイロード
デベロッパー ペイロードは、不正行為の防止や、適切なユーザーへの購入のアトリビューションなど、さまざまな目的で使用されてきました。これらのユースケースは Google Play 請求サービス ライブラリでサポートされるようになったため、Google Play 請求サービス ライブラリのバージョン 2.2 以降ではデベロッパー ペイロードがサポートされなくなっています。詳しくは、デベロッパー ペイロードをご覧ください。
詳細なエラー メッセージ
Google Play 請求サービス ライブラリのバージョン 2.0 以降では、すべてのエラーに、対応するデバッグ関連のメッセージが用意されています。これらのメッセージを取得するには、BillingResult.getDebugMessage()
を呼び出します。