2016年1月21日木曜日

[Android] In-app Billing v3を使ってライセンス購入を実装するLicenseManagerをアップデートしました

憂鬱なムックを助ける友の会: [Android] In-app Billing v3を使ってライセンス購入を実装する で紹介していたLicenseManagerクラスですが、onCreateでnewして、onResumeでisLicensePurchased()メソッドにて購入状態を判定するという作りにしていましたが、onCreateからonResumeが走るまでにIn-app Billing APIが結果を返しきる保証は何もないので、判定を誤るという可能性がありました。

そこで、そのバグ(そう、これはバグです!すみませんっ!!)を修正しましたのでご案内します(そして、コミットログ、ミスりました。。。恥ずかしい。。)

https://github.com/shinchit/LicenseManager

使い方はほぼ変わりません。ただ、newした段階でIn-app Billing APIが結果を返し済みであることを確認してから先の処理に進むように改修していますので、newの直後にisLicensePurchased()メソッドを使っても問題ありません。

技術的には、非同期処理の順番、完了待ちを保証するために、JDeferredというライブラリを利用しています。
そのため、appレベルのbuild.gradleのdependenciesに

 compile 'org.jdeferred:jdeferred-android-aar:1.2.4'

といった記述が必要です(バージョンは適宜調整してください。動作確認をとっているのは1.2.4です)。

JDeferredの細かい使い方については、公式、または次のページがわかりやすいです。

Java - Androidの非同期処理を綺麗に書けるjdeferredが便利! - Qiita

LicenseManagerでは、以下の記述でnewの中でIn-app Billing APIへの非同期リクエストが帰ってくるのを待ち合わせています。

ちなみに、ここではJavaのλ式(ラムダ式)を利用しています。が、別に使わなくても問題ないです^^
ただ、見てお分かりの通り、λ式を使うと型の迂遠な明示が省略できるので楽に読み書きでき、スッキリして見えます。

また、GitHub上のLicenseManagerでは、アプリのライセンスキーを暗号化せずにそのまま渡していますが、実際のリリースapkを作る際にはそれはオススメできません。ライセンスキーは暗号化して保持し、これを復号化してLisenceManagerに渡すようにするべきです。とはいえ、暗号化のseedはapk内に持つため、その気になれば簡単に復号化もできてしまうのですが。。。万全を期すなら、seedを外部のサーバ(Webサーバなど)において、SSLでそれを取得してというのが良いのでしょうが、、、そこまでやる必要もないかと(というか、それをやると実装によってはオフラインでアプリを使用できないシーンが出てくるし)。
この辺の、暗号化・復号化の話はまた別エントリーで取り上げます。

[Android] Android Studioでaarライブラリを取り込む方法

Android Studioでaarで提供されているライブラリをプロジェクトに取り込むには次のようにします。

まず、プロジェクトレベルのbuild.gradleに次のようにflatDirの記述を追加します。

flatDirのdirsのパスは任意のパスを指定できますが、ここでは簡便に使えるプロジェクトのapp/libs/を指定しています。

次に、appレベルのbuild.gradleに次のように取り込むaarファイルの情報を追記します。


ここまで行ったら、プロジェクトのapp/libs/ディレクトリに目的のaarファイル(例ではHogeHoge.aar)を設置します。

あとは、Android StudioでSyncProject(下図の赤枠部)を実行すれば無事にaarがプロジェクトに取り込まれて幸せになれます。

Sync Project with Gradle Filesボタン


参考:
 AndroidStudio - Android Studio でaarをローカルから読み込む方法 - Qiita