普通、体験版といったら、有料版の機能を一部封印しただけの物なので、有料版も体験版も同じプロジェクトにして、スイッチを切り替えるだけですぐビルドできるようにしたいものですが、それをするための手順と工夫の覚え書きです。
それにしても、この話題についてネットで検索すると、当然 Eclipse 時代のノウハウもいっぱい引っかかるのですが、Eclipse の頃はこんな出来て当然の事がものっすごい面倒だったみたいですな。チラ見しただけでもウンザリだよ。Android Studio になってから作り始めてよかった。
Android Studio で体験版用のビルド設定を作りたい
Visual Studio でこういう事をしたい時は 「構成マネージャ」 を使いましたよね。最初からある Debug, Release に加えて、体験版用の TrialDebug, TrialRelease などを追加していって、設定をちょこちょこ変えたものです。Android Studio にも同じような機能があるのですが、設定の切り替えが buildTypes と productFlavors の2種類 に分かれていて、その2つの設定を組み合わせてビルドできます。
buildTypes は主に debug と release ビルドの切り替え に使うために作られてるようで、体験版と有料版など、アプリのエディション分けには productFlavors の方を使うのが一般的らしい。
作ったばかりのプロジェクトには productFlavors は何も用意されてないのですが、例えばそこに pro (=有料版) と trial (=体験版) という2つの productFlavors を作成すれば、その2つと buildTypes の debug, release 2つを組み合わせて、
- proDebug
- proRelease
- trialDebug
- trialRelease
そして定義した buildTypes と productFlavors の設定は、Android Studio の左下あたりにコソっとある 「Build Variants」 というので切り替えられます。目だたなすぎて、最初どこでどうやって変えるのかしばらく分からんかった。 上記は Chronus のプロジェクトの Build Variants ですが、productFlavors は pro (有料版), trial (体験版) の2つ、buildTypes は、debug (開発中), preview (テスター配布用), release (公開版) の3つに分けたので、その組み合わせで6種類からの選択になります。
それとこの Build Variants ですが、変更直後に Run ボタンでアプリを起動すると Build Variants を変える前の apk が起動する事がある ので注意しましょうね。左下のステータスが 「Gradle build finished」 になるまで待った方が安全。
いろいろ設定を変えては起動を繰り返してたら、これのせいで全然意図した通りに動いてくれなくて、かなりムカついた。
buildTypes と productFlavors の記述のしかた
ということで、productFlavors と buildTypes の便利な使い方を書いていきたい訳ですが、もっと親切で詳しいページは他にもいくらでもあるので (参考サイトは後述)、この記事では、僕が有料版と体験版を分ける上で結果的に役に立った事だけをかいつまんで書いていきます。ちなみに、buildTypes や productFlavors の内容は、Android Studio の File > Project Structure からでも編集できるみたいですが、ネット上では build.gradle を直接書き換えるノウハウの方が遥かに豊富なので、たぶん直接書き換えた方が早いし悩まないと思います。
まず基本的な書き方ですが、ここでは例として、productFlavors は pro (有料版) と trial (体験版) の2つ、buildTypes はデフォルトの debug と release の2つとすると、build.gradle の android ブロック内に、以下のように書く事になります。
build.gradle
... android { ... productFlavors { trial { // 体験版向けの設定を書く } pro { // 有料版向けの設定を書く } } buildTypes { debug { // debug ビルド時の設定を書く } release { // release ビルド時の設定を書く } } ... }
buildTypes や productFlavors でリソースやアプリの挙動を変えたい
体験版アプリは有料版の機能を制限したり、タイトルに 「体験版」 とか付けたり、有料版とはあちこち処理や文言を変えたい訳ですが、まずはその方法。Android Studio でプロジェクトを作ると、まず app モジュール内に main ディレクトリが作られて、その中に java や res などが作られますが、それはデフォルトのソースやリソースのファイルです。
ある設定の時だけ文言やアイコンを切り替えたい場合は、 main と同じ階層に buildTypes や productFlavors と同じ名前のフォルダを作り、その中に main と同じ名前のリソースを作れば、その設定の時だけ、そのフォルダのリソースが上書きされる ようになります。
余談ですが、buildTypes の名前のフォルダと productFlavors の名前のフォルダに同名リソースを作ったらどっちが優先されるのかと思って、試しに trial, debug, trialDebug の各フォルダに同名リソースを作ってみたところ、今の Android Studio では trialDebug > debug > trial の順で採用されるようで、つまり buildTypes の方が強いみたい。普通そんな紛らわしい事しませんけどね。
話を戻しましょう。java コードについても基本的には同じで、各設定名のフォルダ内に main と同じ構造の java フォルダを作ってコードを書けばいいのですが、リソースは同名のリソースがあれば上書きされるのに対して、コードは main にデフォルトの処理を書いて、ある設定の時だけ同名のクラスを上書きして処理を変える、という事はできません ので注意。
有料版と体験版で処理を変えたければ、全ての設定名フォルダの中に、同じインターフェースのクラスを実装しないといけません。 ちなみに、ちょっとだけ処理を変えたいくらいなら、わざわざソースファイルから分けなくても、自動で作られる BuildConfig クラスの BUILD_TYPE や FLAVOR でビルド時の設定名が分かりますので、それを調べて処理を変えるという手もあります。
java
if ( BuildConfig.FLAVOR.equals( "trial" ) ) { // 体験版の処理 }
buildTypes や productFlavors でアプリIDを変えたい
有料版と体験版を Google Play で公開する場合、完全に別アプリとしてリリースする事になるので、有料版と体験版のアプリIDは違う物にしないといけません。それに release 版と debug 版についても、アプリIDが同じだと、リリース後に Google Play からインストールしたアプリと開発途中のアプリがごっちゃになって、いろいろ面倒な事になります。
なので、次は buildTypes や productFlavors に応じて、アプリIDを変える方法。
アプリIDは、build.gradle の defaultConfig に、applicationId として記述されてますが、例えばこれを productFlavors ごとに違う値にしたければ、各設定ブロックに分けて書けばOK。
build.gradle
productFlavors { // 体験版 trial { applicationId "com.hikware.testapp.trial" ... } // 有料版 pro { applicationId "com.hikware.testapp" ... } }
そこで代わりに登場するのが applicationIdSuffix 。buildTypes 内に指定すると、applicationId の後に文字列を追加してくれます。例えば、
build.gradle
buildTypes { debug { applicationIdSuffix ".debug" ... } release { ... } }
- proDebug > com.hikware.testapp.debug
- proRelease > com.hikware.testapp
- trialDebug > com.hikware.testapp.trial.debug
- trialRelease > com.hikware.testapp.trial
buildTypes や productFlavors でアプリ名を変えたい
さて、上記で有料版と体験版、debug 版とrelease 版が別のアプリとしてインストールされるようにはなったのですが、このままだとアプリ名もアイコンも一緒のアプリが4つ並ぶ事になるので、全く区別がつきません。アイコンや、せめてアプリ名だけでも変えたいですね。 設定ごとにアプリ名やアイコンを変えたい場合、前述したとおり、main と同じ階層に各設定名のフォルダを作って、同名のリソースを作成すれば変えられるのですが、その方法でアプリ名を変えるとなると、proDebug, proRelease, trialDebug, trialRelease のそれぞれに strings.xml を作らなくちゃない訳で、さらに各国語対応するとそれが倍々に増えていきます。考えただけでウンザリです。なので、極力 strings.xml を増やさなくて済む方法がないか調べてみたのですが、検索したら一応解決出来そうな方法は見つかりました。ありがたい。 でもこの方法、やってる事がかなりトリッキーだし、build.gradle ってアプリごとに作られる物なので、いちいちあんま長々とスクリプトとか書きたくないんですよね。なのでもう少しシンプルにならないかと考えてみた結果、そこそこいい感じになったので、その方法。
- 有料版と体験版でのアプリ名の切り替えについては、おとなしくproductFlavors ごとに strings.xml を分けて対応。ここではアプリ名のリソース名は app_name とします。
-
有料版、体験版それぞれの strings.xml に、debug 版につけたいアプリ名も別途追加します。ここではリソース名は app_name_debug とします。ここまでで、有料版、体験版それぞれの strings.xml は以下の感じ。
pro/res/values/strings.xml (有料版)<resources> <string name="app_name">俺アプリ</string> <string name="app_name_debug">(dbg)俺アプリ</string> </resources>
trial/res/values/strings.xml (体験版)<resources> <string name="app_name">俺アプリ体験版</string> <string name="app_name_debug">(dbg)俺アプリ体験版</string> </resources>
-
build.gradle には、AndroidManifest.xml の内容を置換できる機能、manifestPlaceholders というのがあるので、それを buildTypes の各設定に仕込んで、アプリ名として参照すべきリソース名を置き換える。
build.gradle
buildTypes { debug { // AndroidManifest.xml 内の ${appName} を、続く文字列に置き換える manifestPlaceholders = [appName: '@string/app_name_debug']; ... } release { manifestPlaceholders = [appName: '@string/app_name']; ... } }
-
AndroidManifest.xml 側も、上記の指示によって android:label の内容が置換されるるように、以下のように仕込む。
AndroidManifest.xml
... android:label="${appName}" ...
アイコンについては、有料版と体験版とでだけ変えれば充分なので、trial/res/ と pro/res/ にそれぞれのアイコンを置くだけです。