2016年05月15日

Android Studio でアプリの体験版作りまとめ

 こないだリリースした Chronus もですが、有料販売を前提にしてるアプリは、まずはたくさんの人に触ってもらえるように体験版を作っときたいですよね。
 普通、体験版といったら、有料版の機能を一部封印しただけの物なので、有料版も体験版も同じプロジェクトにして、スイッチを切り替えるだけですぐビルドできるようにしたいものですが、それをするための手順と工夫の覚え書きです。

 それにしても、この話題についてネットで検索すると、当然 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
という4種類からビルド設定が選択できるようになります。個人的には、trialDebug とかより trial-debug のほうが見やすいと思うのだけど、勝手にこうされるので仕方ない。

 そして定義した buildTypes と productFlavors の設定は、Android Studio の左下あたりにコソっとある 「Build Variants」 というので切り替えられます。目だたなすぎて、最初どこでどうやって変えるのかしばらく分からんかった。
20160515a.png
 上記は 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 と同じ名前のリソースを作れば、その設定の時だけ、そのフォルダのリソースが上書きされる ようになります。
20160515b.png
 余談ですが、buildTypes の名前のフォルダと productFlavors の名前のフォルダに同名リソースを作ったらどっちが優先されるのかと思って、試しに trial, debug, trialDebug の各フォルダに同名リソースを作ってみたところ、今の Android Studio では trialDebug > debug > trial の順で採用されるようで、つまり buildTypes の方が強いみたい。普通そんな紛らわしい事しませんけどね。

 話を戻しましょう。java コードについても基本的には同じで、各設定名のフォルダ内に main と同じ構造の java フォルダを作ってコードを書けばいいのですが、リソースは同名のリソースがあれば上書きされるのに対して、コードは main にデフォルトの処理を書いて、ある設定の時だけ同名のクラスを上書きして処理を変える、という事はできません ので注意。
 有料版と体験版で処理を変えたければ、全ての設定名フォルダの中に、同じインターフェースのクラスを実装しないといけません。
20160515c.png
 ちなみに、ちょっとだけ処理を変えたいくらいなら、わざわざソースファイルから分けなくても、自動で作られる BuildConfig クラスの BUILD_TYPE や FLAVOR でビルド時の設定名が分かりますので、それを調べて処理を変えるという手もあります。
java
if ( BuildConfig.FLAVOR.equals( "trial" ) ) {
    // 体験版の処理
}
 が、これだと productFlavors の名前を変えたら動かなくなりますし、有料版のソースやリソースが体験版に含まれてると、解析して有料版に改造する人が出てきますので、有料版の核となるソースは体験版に極力含まない作りにした方がいいとは思います。
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"
        ...
    }
}
 じゃあ buildTypes も同じようにすればいいやん、と思うのですが、それはちょっと甘い。buildTypes と productFlavors は組み合わせて使う物なので、両方に書いたらどっちが採用されるのか分からんですよね。というかそもそも、buildTypes に applicationId を書くとエラーになるみたい。

 そこで代わりに登場するのが applicationIdSuffix 。buildTypes 内に指定すると、applicationId の後に文字列を追加してくれます。例えば、
build.gradle
buildTypes {
    debug {
        applicationIdSuffix ".debug"
        ...
    }
    release {
        ...
    }
}
としておけば、debug 時のみ、アプリIDの末尾に .debug が追加されて、結果的に各設定ごとにアプリIDが別になり、端末にも別のアプリとしてインストールされるようになります。今回の例なら以下のとおり。
  • 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つ並ぶ事になるので、全く区別がつきません。アイコンや、せめてアプリ名だけでも変えたいですね。
20160515d.png
 設定ごとにアプリ名やアイコンを変えたい場合、前述したとおり、main と同じ階層に各設定名のフォルダを作って、同名のリソースを作成すれば変えられるのですが、その方法でアプリ名を変えるとなると、proDebug, proRelease, trialDebug, trialRelease のそれぞれに strings.xml を作らなくちゃない訳で、さらに各国語対応するとそれが倍々に増えていきます。考えただけでウンザリです。

 なので、極力 strings.xml を増やさなくて済む方法がないか調べてみたのですが、検索したら一応解決出来そうな方法は見つかりました。ありがたい。  でもこの方法、やってる事がかなりトリッキーだし、build.gradle ってアプリごとに作られる物なので、いちいちあんま長々とスクリプトとか書きたくないんですよね。なのでもう少しシンプルにならないかと考えてみた結果、そこそこいい感じになったので、その方法。
  1. 有料版と体験版でのアプリ名の切り替えについては、おとなしくproductFlavors ごとに strings.xml を分けて対応。ここではアプリ名のリソース名は app_name とします。
  2. 有料版、体験版それぞれの 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>
    
  3. 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'];
            ...
        }
    }
    
  4. AndroidManifest.xml 側も、上記の指示によって android:label の内容が置換されるるように、以下のように仕込む。
    AndroidManifest.xml
    ...
    android:label="${appName}"
    ...
    
 以上で、strings.xml を無闇に増やさず、build.gradle も複雑化せず、各国語対応もしやすい形で、有料版と体験版、debug 版と release 版でそれぞれアプリ名を変える事ができました。
 アイコンについては、有料版と体験版とでだけ変えれば充分なので、trial/res/ と pro/res/ にそれぞれのアイコンを置くだけです。
20160515e.png
参考にさせていただいたサイト
 この記事の内容は、主に以下のサイトを参考にさせていただきました。どちらの方も、とても丁寧に分かりやすくまとめてくださってて非常に助かりました。
posted by ひこざ at 23:59| Comment(0) | 開発 - Android
この記事へのコメント
コメントを書く
お名前: [必須入力]

メールアドレス:

ホームページアドレス:

コメント: [必須入力]

認証コード: [必須入力]


※画像の中の文字を半角で入力してください。