Hachirog

都内で働いているWebエンジニアのブログです

Androidのアプリ内課金を試してはまる

近況

職場が変わり、Javaの開発から離れ、最近はもはやWebサイトの開発の業務さえ なくなってしまいました。さみしい。

そんな中Androidのネイティブアプリの開発案件が。 Javaの開発経験者だからということで振られたものの、アプリ開発の実業務は今回が初になります。とりあえずやってみたんですが、課金アイテムの購入を試そうとしてドハマりしてしまいました。

結論としてはドキュメントをちゃんと読みましょう、という話なんですが はまったポイントを書き残したいと思います。

課金アイテムの購入ってテストできるのか

アプリ内課金を実装して試している開発段階で、実際の請求が発生したらたまりません。 課金をテストできる仕組みはやはりちゃんとあるみたいですね。

http://developer.android.com/google/play/billing/billing_testing.html

テストのやり方には2つの方法があるようで

  • 開発中のアプリをalpha/beta版に登録する
  • Static Responsesを使う

前者の方法だとアプリ登録の手間があるので、手軽ではありません。

Static Responsesを利用する方法ではGoogle Play側で用意されている テスト用のプロダクトIDをリクエストします。まず課金の実装を試すなら こちらがおすすめとドキュメントにも書いてあります。

アプリ内課金を試す

実装方法の説明はこちら

http://developer.android.com/google/play/billing/billing_integrate.html

ドキュメントに沿って開発していたんですが、所々つまづいてしまい・・・

AIDLの追加

IInAppBillingService.aidlを追加せよとあります。 AIDLファイルというものは今回お初にお目にかかったのですが、 調べてみるとプロセス間通信を実現するためのものとか。

そしてプロジェクトへの追加の仕方が独特

  1. SDK ManagerでGoogle Play Billing Libraryをダウンロード
  2. IInAppBillingService.aidlファイルをコピー
  3. プロジェクト内にパッケージ(com.android.vending.billing)をつくる
  4. コピーしたファイルをペースト
  5. ビルドする(IInAppBillingService.javaができる)

依存関係を追記すればOK、というわけにはいかないんですね。 しかもドキュメントの手順説明がEclipse向けに書いてあって少し戸惑いました。 (正式サポートがきれるっていう話だからAndroid Studioで開発したのに・・・。 少し勝手が違いましたが、Android Studioでも組み込めました)

実装する。そしてはまる

ドキュメントに実装例が記載されています。 そちらにしたがって実装、エミュレータで実行してみたものの NullPointerExceptionが発生してしまい、うまくいきません。 実装をチェックしても間違っていそうな箇所はなく 原因を検索してみたものの、これといった情報にはヒットせず。

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);
   }
};

どうもonServiceConnectedが呼び出されず、mServiceがnullのまま。 StackOVerflowにも同じ悩みを抱えている方がいるようですが、 回答の内容を試してみたものの結局解決にいたりませんでした。

http://stackoverflow.com/questions/10635512/android-in-app-billing-null-pointer-exception

半日くらい右往左往していたところ、公式ドキュメントをよく読むとこんな記述が!

To test In-app Billing in an application you must install the application on an Android-powered device.

アプリ内課金は実機でテストしないとダメでした・・・。 エミュレータではテストできません!

ドキュメントをよく読んでなかった私が悪いのですが、 「アプリ内課金はエミュレータでテストできません」とか エラーメッセージが出てくれたら嬉しいんだけどなあ。

  • USBケーブル経由で実機にアプリを入れる
  • 実機には開発者アカウントまたはテストアカウントでログインする
  • 実機のGoogle Play Serviceのバージョンを5.0.12以上にする

これで、サンプルアプリがNullPointerExceptionで落ちずに めでたくアイテム購入のダイアログが出てきました。

Unexpected response code 500 が出たので待つ

ひとまず購入処理をひと通り試すことができました。 安心したところでリファクタリングし、そして再度購入処理を試しました。 しかし失敗。

コンソールには

BasicNetwork.performRequest:Unexpected response code 500

と出ています。 500というとInternal Server Errorですね。 Google Play側のサーバが不調なのか、ということで待機。 結局回復せず、続きは翌日に持ち越しました。 そして日をまたいでからまた試してみるも失敗。

ここまでサーバの調子が悪いのはおかしい、ということで調べてみるとこんな記述が。

http://developer.android.com/google/play/billing/api.html#consume

Once an in-app product is purchased, it is considered to be “owned”. In-app products in the “owned” state cannot be purchased from Google Play.

一度購入したアイテムは消費処理をしないと、再度購入することができないようです。 そこでconsumePurchaseメソッドを実行してから、 アイテムを再度購入する、という処理にしてみると無事成功!

これもドキュメントを読んでいなかった私が悪いんですが、 そもそもこのレスポンスコード500って何なんですかね・・・。 400(Bad Request)とか403(Forbbiden)あたりだったら早く原因調査に乗り出したのに。

 まとめ

  • Androidの課金テストには実機が必要。エミュレータで出来ない。
  • 一度買ったアイテムは消費しないと再購入できない。
  • ドキュメントはすみずみまで読まないとだめ。

以上、Androidのアプリ内課金を試す際の覚書でした。