Ⅲ. 実装方法
1. AndroidManifest.xml にアプリ内課金の権限を追加する
<uses-permission androidname="com.android.vending.BILLING" />
2. IInAppBillingService.aidl をプロジェクトに追加する
(android sdk)/extras/google/play_billing/IInAppBillingService.aidl ※1 を
プロジェクトのapp/aidl/com/android/vending/billing/IInAppBillingService.aidl ※2 にコピーします
※1
デフォルトで C:\Users\%username%\AppData\Local\Android\sdk\extras\google\play_billing\IInAppBillingService.aidl にあります
※2
(android project name)\app\src\main\aidl\com\android\vending\billing\IInAppBillingService.aidl にコピーします
3. IInAppBillingService にバインドする
公式ドキュメントの通りです
IInAppBillingService mService;
ServiceConnection mServiceConn = new ServiceConnection() {
@Override
public void onServiceDisconnected(ComponentName name) {
mService = null;
}
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
mService = IInAppBillingService.Stub.asInterface(service);
}
};
公式ドキュメントの通りです
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Intent serviceIntent =
new Intent("com.android.vending.billing.InAppBillingService.BIND");
serviceIntent.setPackage("com.android.vending");
bindService(serviceIntent, mServiceConn, Context.BIND_AUTO_CREATE);
}
5. Activity 終了時にアプリ内課金サービスのバインドを解除する
公式ドキュメントの通りです
解除しないと端末のパフォーマンス低下につながります
@Override
public void onDestroy() {
super.onDestroy();
if (mService != null) {
unbindService(mServiceConn);
}
}
6. 簡単に Activity のレイアウトを作る
ボタン名 |
機能 |
BUY |
アプリ内課金を実行するボタン |
CHECK |
アプリ内課金の状態を取得するボタン |
USE |
アプリ内課金で購入したアイテムを消費※3する |
※3 消費とは
同じ課金アイテムを重複して買うことは出来ません。
同じ課金アイテムを重複して買わせるためには、
購入したものを消費する必要があります。
継続課金(定期購入)は消費できません。
7. ボタンを変数に割り当てる
onCreate
button1 = (Button)findViewById(R.id.button);
button2 = (Button)findViewById(R.id.button2);
button3 = (Button)findViewById(R.id.button3);
8. 購入ボタン(BUY)を実装する
onCreate
button1.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
buy();
}
});
buy
RESPONSE_CODE一覧は以下のサイトに書かれています。
必要に応じて適切に実装して下さい。
https://developer.android.com/google/play/billing/billing_reference.html?hl=ja#billing-codes
private void buy() {
try {
Bundle buyIntentBundle = billingService.getBuyIntent(3, getPackageName(), "item001", "inapp", "hoge");
int response = buyIntentBundle.getInt("RESPONSE_CODE");
if(response == 0) {
PendingIntent pendingIntent = buyIntentBundle.getParcelable("BUY_INTENT");
startIntentSenderForResult(
pendingIntent.getIntentSender(),
1001,
new Intent(),
Integer.valueOf(0),
Integer.valueOf(0),
Integer.valueOf(0));
}
else if(response == 1) {
alert("購入がキャンセルされた");
}
else if(response == 7){
alert("既に同じものを購入している");
}
} catch(Exception e) {
e.printStackTrace();
alert("buy unsuccessfully finished.");
}
}
onActivityResult
課金の結果を取得する
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
if (requestCode == 1001) {
int responseCode = data.getIntExtra("RESPONSE_CODE", 0);
String purchaseData = data.getStringExtra("INAPP_PURCHASE_DATA");
if (resultCode == RESULT_OK) {
try {
JSONObject jo = new JSONObject(purchaseData);
String productId = jo.getString("productId");
alert("購入成功しました");
}
catch (JSONException e) {
alert("Failed to parse purchase data.");
e.printStackTrace();
}
} else {
alert("課金に失敗しました");
}
}
}
8. 消費ボタン(USE)を実装する
onCreate
button2.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
use();
}
});
use
private void use() {
try {
Bundle ownedItems = billingService.getPurchases(3, getPackageName(), "inapp", null);
int response = ownedItems.getInt("RESPONSE_CODE");
if (response == 0) {
ArrayList<String> ownedSkus = ownedItems.getStringArrayList("INAPP_PURCHASE_ITEM_LIST");
ArrayList<String> purchaseDataList = ownedItems.getStringArrayList("INAPP_PURCHASE_DATA_LIST");
ArrayList<String> signatureList = ownedItems.getStringArrayList("INAPP_DATA_SIGNATURE_LIST");
String continuationToken = ownedItems.getString("INAPP_CONTINUATION_TOKEN");
for (int i = 0; i < purchaseDataList.size(); ++i) {
String purchaseData = purchaseDataList.get(i);
JSONObject object = new JSONObject(purchaseData);
String productId = object.getString("productId");
String purchaseToken = object.getString("purchaseToken");
response = billingService.consumePurchase(3, getPackageName(), purchaseToken);
if(response == 0) {
alert(productId + "を消費しました。");
} else {
alert(purchaseData);
}
}
}
}catch(Exception e) {
e.printStackTrace();
}
}
9. アプリ内課金の状態を取得するボタン(CHECK)を実装する
先程の use 関数から消費処理を消すだけです。
onCreate
button3.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
check();
}
});
check
private void check() {
try {
Bundle ownedItems = billingService.getPurchases(3, getPackageName(), "inapp", null);
int response = ownedItems.getInt("RESPONSE_CODE");
if (response == 0) {
ArrayList<String> ownedSkus = ownedItems.getStringArrayList("INAPP_PURCHASE_ITEM_LIST");
ArrayList<String> purchaseDataList = ownedItems.getStringArrayList("INAPP_PURCHASE_DATA_LIST");
ArrayList<String> signatureList = ownedItems.getStringArrayList("INAPP_DATA_SIGNATURE_LIST");
String continuationToken = ownedItems.getString("INAPP_CONTINUATION_TOKEN");
for (int i = 0; i < purchaseDataList.size(); ++i) {
String purchaseData = purchaseDataList.get(i);
JSONObject object = new JSONObject(purchaseData);
String productId = object.getString("productId");
String purchaseToken = object.getString("purchaseToken");
alert(productId + "," + purchaseToken);
}
}
}catch(Exception e) {
e.printStackTrace();
}
}
10. APKを作成する
必ず署名をしてAPKを作成して下さい。
署名をしないと以下のようになります。
このバージョンのアプリには、Google Playを通じたお支払はご利用になれません。
詳しくはヘルプセンターをご覧ください。
12. アプリ公開に必要な情報を全て入力する(コンテンツレーティングなど)
13. アプリ内課金アイテムを追加する
14. テスト用のアクセス権がある Gmail アカウントを追加する
Google Play Devloper Console の左端にある設定(歯車アイコン)→アカウントの詳細
15. アプリを公開する
公開完了まで数時間かかるので待つ。
16. 課金テストする。
購入テスト時には、必ず「これはテスト用です」と書かれていることを確認して下さい。
確認しないと実際に課金されます。
Google Play の手数料は30%です。
取引手数料