Android アプリ内課金を使って無料版アプリをプレミアム版にアップグレードするアプリを開発する手順

Google Play In-app Billing

1.概要

Google Play のサービスで、アプリケーション内からデジタルコンテンツを販売出来る。

ダウンロード可能な写真のようなものから、ゲームのレベルや機能などの仮想コンテンツまで幅広いコンテンツを販売出来る。

販売方法には

  1. 標準型(one-time billing)
  2. 購読型(recurring, automated billing)

があり、どちらの方法でも、Google Play が管理するためアプリケーションが直接金銭取引に関与する必要はない。バックエンドサービスが購買に利用される。

Google Play を通して公開されているアプリケーションならこれらを行うことができる。

行うのには、Google Play Developer アカウント および Google Wallet マーチャントアカウント以外に特別なアカウントは必要ない。

2.準備

2.1 サービスインターフェースの追加

IInAppBillingService.aidl をアンドロイドプロジェクトに追加する必要がある。

Android SDK Managerを立ち上げて、Extras の中にある、Google Play Billing Library にチェックを入れてインストールを実施

android_in_app_billing_sdk_download

インストールが完了すると、<sdkディレクトリ> の以下のフォルダに、IInAppBillingService.aidlがあるので、自分のプロジェクトに取り込む。

<sdkディレクトリ>\extras\google\play_billing\samples\TrivialDrive\src\com\android\vending\billing

Eclipse の場合、src ディレクトリに com\android\vending\billing というパッケージが作成されるようにインポートすればよい。

android_in_app_billing_import_aidl_file

取り込んだあとは、以下のように com\android\vending\billing  と、自分のアプリ(info\typea\eitangoroid2) がsrc ディレクトリに並ぶ形になる。

また、gen ディレクトリ配下の com\android\vending\billing に、IInAppBillingService.java が 自動生成される。

android_in_app_billing_imported_aidl_file

2.2 ヘルパークラスの取り込み

また上記ライブラリをインストールすると、サンプルアプリケーション   TrivialDrive  が、以下のフォルダに含まれている。(新規にアプリを作成する場合、これをリファクタリングで名前変更すればよいようだ)

<SDKディレクトリ>extras\google\play_billing\samples\TrivialDrive\src\com\example\android\trivialdrivesample

この中の util ディレクトリにヘルパークラスが含まれているので、フォルダごと自分のアプリケーションに取り込む。自分はすでにutil パッケージが存在したので、配下に billing パッケージを作成しその中にクラス群を取り込んだ。

取り込んだ後、取り込んだクラスのパッケージを適宜変更する。

 

android_in_app_billing_helper_classes_imported

2.3 ライセンスキー

ここまでで、一旦APKファイルを作成し、アップロードすると、アプリ内課金を行うのに必要な、ライセンスキーが得られる、これはデベロッパーコンソールの、サービスとAPIに記載されている。

android_in_app_billing_licens_key

このライセンスキーをプログラムにハードコーディングしないことをセキュリティ的に強く推奨されている。

ライセンスキー全体を、部分から実行時に生成するか、暗号化しておくことが推奨されているので、Base64 風のでたらめな文字列の中にライセンスキーを埋め込み、実行時に取り出すようにしてみる。

以下は、PythonででたらめなBase64風文字列を作成する例。実行時に特定の位置を切り出して利用するようにしてみる。

  1. >>> import string
  2. >>> from random import choice
  3. >>> print "".join([choice(string.ascii_lowercase + string.ascii_uppercase + string.digits + '+/') for i in range(200)])
  4. b7XWPqVG0+FWMDWqJui8qI9f400dUMm3mzATE4ToLAKMK3sWTU3nnnF6GkepBlnh8P+nQMDL/PmJJLajB6EnouXl1KleMsgMro1mshOnbOm/JwprEb55c2al3sodwqWIRNRYVJHvIjmjH4jP9dzYfhkkOCM7CAV+ncvU1uErSvYzb+lf9O9py0ad20vVgyElXTzD2rt8

2.4 パーミッション設定

以下のパーミッションを AndroidManifest.xml に追加

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

3.Google Playとの接続

Google Play と接続するために、アプリ内課金リクエストをGoogle Play へアプリケーションから送信する必要がある。上記で取り込んだ、util パッケージにヘルパークラスがあり、同期接続を行うには、 IabHelper  クラスのインスタンス化を Activity の onCreate で行う

3.1 Google Play のアプリ内課金サービスに接続する例

onCreate() で接続

  1. @Override
  2. protected void onCreate(Bundle savedInstanceState) {
  3. super.onCreate(savedInstanceState);
  4. String publicKey = getString(R.string.publicKey);
  5. billingHelper = new IabHelper(
  6. this,
  7. publicKey.substring(111 /*キーの前に付与したダミーの桁*/,
  8. publicKey.length()-999 /*キーの後ろに付与したダミーの桁*/));
  9. // 製品版の場合、false とする
  10. billingHelper.enableDebugLogging(true);
  11. billingHelper.startSetup(new IabHelper.OnIabSetupFinishedListener() {
  12. public void onIabSetupFinished(IabResult result) {
  13. if (!result.isSuccess()) {
  14. Log.d(Eitangoroid2Application.TAG, "Problem setting up In-app Billing: " + result);
  15. }
  16. // Hooray, IAB is fully set up!
  17. }
  18. });
  19. }

onDestroy() で破棄する

  1. @Override
  2. public void onDestroy() {
  3. if (billingHelper != null) {
  4. billingHelper.dispose();
  5. }
  6. billingHelper = null;
  7. }

一旦、実行すると接続に成功したことを LogCatで確認出来た。

android_in_app_billing_connect_log

 

4.商品の登録

Google Play に接続までできたので、実際に販売する商品を登録する必要がある。

登録はデベロッパーコンソールから行う。

アプリ内アイテム を選択し

android_in_app_billing_before_apk_upload

新しいアイテムを追加

android_in_app_billing_first_item

今回は、無料版をアップグレードさせるつもりなので、管理対象のアイテムを選び、ユニークなアイテムIDを登録する。このIDは後で変更出来ないとのこと。

アプリ内サービスIDのガイドライン

サービス ID は、同じアプリのすべてのアイテムにわたって固有でなければならず、後で再利用することもできません。

android_in_app_billing_managed_item

とりあえず、適当に説明を書いて保存する。

android_in_app_billing_item_notes

5.製品の問い合わせ

作成した商品をGoogle Play に問い合わせてみる。先ほど、onCreate() に追加したブロックから、queryInventoryAsync() を使って問い合わせ。結果はmGotInventoryListener で受け取る。

SKU_PREMIUM_UPGRADE は、商品に付与したサービスID。

  1. billingHelper.startSetup(new IabHelper.OnIabSetupFinishedListener() {
  2. public void onIabSetupFinished(IabResult result) {
  3. if (!result.isSuccess()) {
  4. Log.d(Eitangoroid2Application.TAG, "Problem setting up In-app Billing: " + result);
  5. }
  6. Log.d(Eitangoroid2Application.TAG, "// Hooray, IAB is fully set up! : " + result);
  7. billingHelper.queryInventoryAsync(
  8. true,
  9. Arrays.asList(new String[]{SKU_PREMIUM_UPGRADE}),
  10. mGotInventoryListener);
  11. }
  12. });

結果を受け取ることができたらログに出力。

  1. IabHelper.QueryInventoryFinishedListener mGotInventoryListener
  2. = new IabHelper.QueryInventoryFinishedListener() {
  3. public void onQueryInventoryFinished(IabResult result,
  4. Inventory inventory) {
  5.  
  6. if (result.isFailure()) {
  7. // handle error here
  8. return;
  9. }
  10. else {
  11. // does the user have the premium upgrade?
  12. //mIsPremium = inventory.hasPurchase(SKU_PREMIUM);
  13. // update UI accordingly
  14. SkuDetails skuDetails = inventory.getSkuDetails(SKU_PREMIUM_UPGRADE);
  15. if (skuDetails == null) {
  16. Log.i(Eitangoroid2Application.TAG,"skuDetails is null");
  17. } else {
  18. Log.i(Eitangoroid2Application.TAG,
  19. String.format("%s %s", skuDetails.getDescription(),skuDetails.getPrice()));
  20. }
  21. isPremium = inventory.hasPurchase(SKU_PREMIUM_UPGRADE);
  22. }
  23. }
  24. };

アプリを実行し、LogCatで商品情報が取得できたことを確認。

android_in_app_billing_get_skudetail

6.製品の購入

製品購入のコードを書く。自アプリでは、onOptionItemSelected で購入させる。launchPurchaseFlow()を呼び出す。下例で、10001 としている箇所には、任意の数値を指定すると、Google Playがこの値を結果として返してくる。

  1. @Override
  2. public boolean onOptionsItemSelected(MenuItem item) {
  3. boolean ret = true;
  4. switch(item.getItemId()) {
  5. case R.id.action_upgrade:
  6. billingHelper.launchPurchaseFlow(
  7. this,
  8. SKU_PREMIUM_UPGRADE,
  9. 10001,
  10. mPurchaseFinishedListener);
  11. break;
  12. default:
  13. ret = super.onOptionsItemSelected(item);
  14. }
  15. return ret;
  16. }

// TODO に、購入が成功した場合のコードを記述する

  1. IabHelper.OnIabPurchaseFinishedListener mPurchaseFinishedListener
  2. = new IabHelper.OnIabPurchaseFinishedListener() {
  3. public void onIabPurchaseFinished(IabResult result, Purchase purchase)
  4. {
  5. if (result.isFailure()) {
  6. Log.d(Eitangoroid2Application.TAG, "Error purchasing: " + result);
  7. return;
  8. } else if
  9. (purchase.getSku().equals(SKU_PREMIUM_UPGRADE)) {
  10. // TODO
  11. }
  12. }
  13. };

 

7.テスト

7.1 取引について

さて、テストだがアプリケーション公開前に、アルファ版、ベータ版を利用してテストユーザーにテストを実施してもらうことが出来る。Google Playは注文により金銭の取引が発生するのを防ぐために、自動的に14日でキャンセルされる。これにより、アカウントへの変更は発生しない。

7.2 テストユーザーの登録

https://support.google.com/googleplay/android-developer/answer/3131213?hl=ja

android_in_app_billing_alfa_tester

デベロッパーコンソールから、テストユーザーの管理をクリックすることで、テストユーザーを登録できるのだが、GoogleグループかGoogle+コミュニティかを指定する必要がある。

ということで、アプリテスト用のGoogle+コミュニティを開設してみた。

手順は以下参照

Google+コミュニティ

https://plus.google.com/u/0/communities/109736718368840290206

アプリのアルファテスト版を提供するユーザーで、Google+コミュニティを追加とあるのだが、ここには、Google+コミュニティのURLを入力する。

Google+ コミュニティの URL または Google グループのメール アドレスをデベロッパー コンソールに追加

何を入力したらいいのかわからず、しばらく悩んだ。

android_in_app_billing_google_plus_success

下段のリンクにアクセスすると、テストユーザーでアルム旨確認でき、Google Play へのリンクが張ってある。

android_in_app_billing_be_tester

 

android_in_app_billing_alfa_publish

7.3 開発者本人だとエラー

想定していたけど、開発者本人アカウントだとエラーになってしまう。

通常でも有料アプリは開発者本人が購入することができないので、想定内ではあるが、いちいち他人に頼んだりするのは面倒なので自分でテストができるとよいのだけれど。

 android_in_app_billing_fail

7.4 知人のアカウントで確認

知人をGoogle+コミュニティーに招待し、参加を承諾してもらった上で、上記URLを通知し、先ほどと同様にアプリをダウンロードして、購入を試してみる。

今度は問題なく購入に進むことができた。

android_inapp_billing_parchase

購入後、想定通り広告が表示されないことも確認できた!

 

8.製品版として公開

製品版に移行ボタンを押してみる。

android_in_app_billing_goto_product

現在公開バージョンとの衝突(?)が注意されるので、現在公開バージョンを無効にする。

android_in_app_billing_goto_product2

あらためて、最新版を公開。

android_in_app_billing_goto_product3

 

以上めでたしめでたし!

Follow me!

コメントを残す

メールアドレスが公開されることはありません。 * が付いている欄は必須項目です