Rubyとクラウドサービスで実現したEC決済共通基盤@Ruby Association ビジネスセミナー201401
Play Billing Libary
1. Copyright (C) 2017 DeNA Co.,Ltd. All Rights Reserved.
2017/07/25
Shigehiro Soejima
Play Billing Library
2. Copyright (C) 2017 DeNA Co.,Ltd. All Rights Reserved.
Play Billing Library
https://developer.android.com/google/play/billing/billing_library.html
https://www.youtube.com/watch?v=9chvh1WYCvw
https://developer.android.com/training/play-billing-library/index.html
https://android-developers.googleblog.com/2017/06/money-made-easily-
with-new-google-play.html
https://github.com/googlesamples/android-play-
billing/tree/master/TrivialDrive_v2
1
3. Copyright (C) 2017 DeNA Co.,Ltd. All Rights Reserved.
下準備
パーミッションを追加
<uses-permission android:name="com.android.vending.BILLING" />
dependenciesを追加
dependencies {
compile 'com.android.billingclient:billing:dp-1'
}
2
4. Copyright (C) 2017 DeNA Co.,Ltd. All Rights Reserved.
Play Billingサービス利用までの基本実装手順
1. PurhcasesUpdatedListenerを実装
2. BillingClientStateListenerを実装
3. BillingClientの作成
4. IABサービスに接続
5. コールバックでセットアップ完了を確認
5まで正常終了した段階でクエリ、購入等のアプリ別の実装が可能となる。
3
5. Copyright (C) 2017 DeNA Co.,Ltd. All Rights Reserved.
public class MainActivity extends AppCompatActivity implements BillingClientStateListener, PurchasesUpdatedListener {
private static final String TAG = "PBL Sample";
private BillingClient mBillingClient;
private TextView mTextView;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
setSupportActionBar(toolbar);
FloatingActionButton fab = (FloatingActionButton) findViewById(R.id.fab);
fab.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
launchPurchase();
}
});
mTextView = (TextView) findViewById(R.id.textView);
mBillingClient = new BillingClient.Builder(this).setListener(this).build();
mBillingClient.startConnection(this);
}
@Override
public void onBillingSetupFinished(int resultCode) {
if (resultCode == BillingClient.BillingResponse.OK) {
Log.d(TAG, "Billing setup successful");
queryPurchases();
} else {
Log.d(TAG, "Billing setup failed");
}
}
@Override
public void onBillingServiceDisconnected() {
Log.d(TAG, "Billing setup failed");
}
@Override
public void onPurchasesUpdated(int responseCode, List<Purchase> purchases) {
switch (responseCode) {
case BillingClient.BillingResponse.OK: {
Log.d(TAG, "onPurchasesUpdated: OK");
break;
}
case BillingClient.BillingResponse.USER_CANCELED: {
Log.d(TAG, "onPurchasesUpdated: User canceled");
break;
}
default: {
Log.d(TAG, "onPurchasesUpdated: responseCode=" + responseCode);
}
}
}
private void queryPurchases() {
List<String> skuList = new ArrayList<>();
skuList.add("premium");
skuList.add("gas");
skuList.add("dummy"); // non-existing id
mBillingClient.querySkuDetailsAsync(BillingClient.SkuType.INAPP, skuList, new SkuDetailsResponseListener() {
@Override
public void onSkuDetailsResponse(SkuDetails.SkuDetailsResult result) {
if (result.getResponseCode() == BillingClient.BillingResponse.OK) {
List<SkuDetails> list = result.getSkuDetailsList();
if (list.size() != 0) {
for (SkuDetails sd : list) {
mTextView.append(sd.toString() + "nn");
}
} else {
Toast.makeText(MainActivity.this, "No purchases yet", Toast.LENGTH_LONG).show();
}
} else {
Log.d(TAG, "Query failed: (response code=" + result.getResponseCode() + ")");
}
}
});
}
private void launchPurchase() {
BillingFlowParams params = new BillingFlowParams.Builder()
.setSku("gas")
.setType(BillingClient.SkuType.INAPP)
.build();
mBillingClient.launchBillingFlow(this, params);
}
}
4
6. Copyright (C) 2017 DeNA Co.,Ltd. All Rights Reserved.
1. PurchasesUpdatedListenerを実装
購入処理にかかわるコールバックの実装を行う。
PurchasesUpdatedListener#
onPurchasesUpdated(@BillingClient.BillingResponse responseCode: Int, purchases: List<Purchase>?)
BillingClientのインスタンス作成に必要なので先に(空)実装する。
セットアップ、購入時等の非同期処理のresponseCodeは正常終了の
BillingClient.BillingResponse.OKの他に、
BillingClient.BillingResponse.BILLING_UNAVAILABLEなど全部で11種類
あるので、それぞれアプリの仕様に従って処理を実装。
5
7. Copyright (C) 2017 DeNA Co.,Ltd. All Rights Reserved.
2. BillingClientStateListenerを実装
BillingClientのセットアップ処理のコールバック。
BillingClientStateListener#
onBillingSetupFinished(@BillingClient.BillingResponse resultCode: Int)
onBillingServiceDisconnected()
アプリを起動して最初に必要な処理を行う部分。
裏でマーケットアプリが更新されていたりすると接続が切られることも。
6
8. Copyright (C) 2017 DeNA Co.,Ltd. All Rights Reserved.
3. BillingClientの作成
実際にクエリや購入の操作を行うクラス。
private lateinit var billingClient: BillingClient
…
billingClient = BillingClient.Builder(this).setListener(this).build()
ビルダーを使ってインスタンス作成。setListenerで1.で実装した
PurchasesUpdateListenerを渡す。
7
9. Copyright (C) 2017 DeNA Co.,Ltd. All Rights Reserved.
4. IABサービスに接続
billingClient.startConnection(this)
2.で作成したBillingClientStateListenerのインスタンスを渡す。
非同期で接続処理が開始される。
8
10. Copyright (C) 2017 DeNA Co.,Ltd. All Rights Reserved.
5.コールバックでセットアップ完了を確認
override fun onBillingSetupFinished(@BillingClient.BillingResponse resultCode: Int) {
if (resultCode == BillingClient.BillingResponse.OK) {
// 接続完了、購入状態の確認等
} else {
// 接続失敗、リトライ・エラーメッセージの表示等
}
}
BillingClient.BillingResponse.OKでセットアップが正しく完了。ここまでがすべての
アプリ共通で必要な処理。
正しく完了したら、プロダクトの購入状態をチェックしてUIを更新する等のアプリ独
自の処理を実装する。
9
11. Copyright (C) 2017 DeNA Co.,Ltd. All Rights Reserved.
プロダクト購入状態の確認
BillingClientのquerySkuDetailsAsync等のqueryXXXで取得する。
billingClient.querySkuDetailsAsync(BillingClient.SkuType.INAPP, skuList) {
// SkuDetailsResponseListener#onSkuDetailsResponse(SkuDetailsResult)
if (it.responseCode == BillingClient.BillingResponse.OK) {
if (it.skuDetailsList.size != 0) {
for (skuDetails in it.skuDetailsList) {
// UIを更新等のアプリの処理
}
} else {
// まだ何も購入していない
}
…
10
12. Copyright (C) 2017 DeNA Co.,Ltd. All Rights Reserved.
プロダクト購入の開始
val params = BillingFlowParams.Builder()
.setSku(“gas”)
.setType(BillingClient.SkuType.INAPP)
.build()
billingClient.launchBillingFlow(this, params)
11
13. Copyright (C) 2017 DeNA Co.,Ltd. All Rights Reserved.
サンプルコード
https://github.com/mightyfrog/Play-Billing-Library-Sample
12