読者です 読者をやめる 読者になる 読者になる

やらなイカ?

たぶん、iOS/Androidアプリの開発・テスト関係。

Gradle+Androidプラグインでプロダクトフレーバーを試してみた

Androidの新ビルドシステム(Gradle + Gradle plugin for Android)では、プロダクト・フレーバーという仕組みによってひとつのプロジェクトから複数の(異なるPackageNameを持つ)apkをビルドできます。

これによって、以下のようなものを容易に提供することができるようになります。

  • 画像リソースなどの異なる、同じ仕組みのアプリ
  • 無料版と有料版
  • ステージングサーバに接続するといった、開発中に使用するアプリ
  • 異なるSDkバージョン、異なるアーキテクチャに最適化したアプリ

Gradleの実行環境は前記事 Gradle+AndroidプラグインでNDKプロジェクトをビルドする - やらなイカ? 参照。これに加え今回は Android Studio 0.1 をプロジェクトのひな形作りに使用します。

新規プロジェクトの作成

プロダクト・フレーバーを使用するには、従来のEclipseのプロジェクト構成ではなく、Gradleの流儀に従う必要があります。

新しい開発環境であるAndroid Studioで新規プロジェクトを作成すると、Gradle向きの構成で生成されます。 既存プロジェクトの場合は、これに合わせてディレクトリ階層を変更するなどする必要があります。

GradleAndroidFlavorExampleのディレクトリ構成(新規作成時点)

  • GradleAndroidFlavorExample/
    • build/
    • build.gradle
    • libs/
    • src/
      • main/ (Eclipseにおけるプロジェクトホーム)
        • AndroidManifest.xml
        • ic_launcher-web.png
        • java/ (Eclipseにおけるsrc/ディレクトリ)
        • res/
  • build.gradle
  • gradle/
    • wrapper/
      • gradle-wrapper.jar
      • gradle-wrapper.properties
  • gradlew
  • gradlew.bat
  • local.properties
  • settings.gradle

IntelliJ IDEAのプロジェクトファイルおよび、リポジトリ管理外のファイルは除いています。

ライブラリプロジェクトを追加

フレーバーに先立ち、ライブラリプロジェクトを追加してみます。ライブラリプロジェクトは、プロジェクト直下にlibraries/ディレクトリを作り、その下に配置します。 今回は BoD/android-switch-backport · GitHub を置いてみます。

  • GradleAndroidFlavorExample/
  • build.gradle
  • gradle/
  • gradlew
  • gradlew.bat
  • libraries/
    • android-switch-backport/
      • AndroidManifest.xml
      • res/
      • src/
  • local.properties
  • settings.gradle

ライブラリプロジェクト自体のbuild.gradleは以下のように定義します。

buildscript {
    repositories {
        mavenCentral()
    }

    dependencies {
        classpath 'com.android.tools.build:gradle:0.4'
    }
}

apply plugin: 'android-library'

android {
    compileSdkVersion 17
    buildToolsVersion "17.0.0"

    sourceSets {
        main {
            manifest.srcFile 'AndroidManifest.xml'
            java.srcDirs = ['src']
            resources.srcDirs = ['src']
            aidl.srcDirs = ['src']
            renderscript.srcDirs = ['src']
            res.srcDirs = ['res']
            assets.srcDirs = ['assets']
        }
    }
}

導入したライブラリプロジェクトのディレクトリ構成が異なるので、sourceSets{}の記述が必要です。

尚、Gradle Plugin User Guide - Android Tools Project Site にはbuildToolsVersionが書かれていませんが、これも必要です。 アプリケーションプロジェクトと同じバージョンを指定する必要があるようです。*1

続いて、追加したライブラリプロジェクトの存在をsettings.gradleに追加します。

include ':GradleAndroidFlavorExample', ':libraries:android-switch-backport'

最後に、アプリケーションプロジェクトのbuild.gradleに、このライブラリプロジェクトを追加します。

dependencies {
    compile files('libs/android-support-v4.jar')
    compile project(':libraries:android-switch-backport')   //←コレ
}

【5/15追記】 buildscript {}は、プロジェクト個々にではなく、プロジェクトのルートにあるbuild.gradle(Android Studioで生成すると空のファイル)一箇所に書くだけでいいようです。
commit: 477fa36 参照。

プロダクト・フレーバーを追加

アプリケーションプロジェクトに、ふたつのプロダクト・フレーバーを追加してみます。まず、build.gradleのandroid{}内に以下を追加します。 packageNameなど、AndroidManifest.xmlの内容を上書きすることができます。

productFlavors {
    squid {
        packageName "com.nowsprinting.gradleandroidflavorexample.squid"

    }
    cuttlefish {
        packageName "com.nowsprinting.gradleandroidflavorexample.cuttlefish"

    }
}

続いて、フレーバーごとの差分を作成します。アプリケーションの"main"と同列に、build.gradleに定義したフレーバー名と同じ名前のディレクトリを作り、その下に差分のファイルを配置します。

今回の例ではイカのようになります。

  • GradleAndroidFlavorExample/
    • src/
      • main/
      • squid/
        • res/
          • values/
      • cuttlefish/
        • res/
          • values/

それぞれのstrings.xmlは、app_nameと表示メッセージを書き換えてあります。画像リソース、Javaソースなど、差分だけ置けば適切に取り込まれます。

尚、今回はAndroidManifest.xmlもmain/のみでフレーバーごとのディレクトリには配置していません。build.gradleのフレーバー定義に書く以上の差分がなければ、main/下のみにひとつあればいいようです。

フレーバーをビルドする

Gradleのサブコマンドassembleにフレーバー名を追加して指定することで、そのフレーバーをビルドできます。

$ gradlew assembleCuttlefish

これで、GradleAndroidFlavorExample/build/apk/下に、

  • GradleAndroidFlavorExample-cuttlefish-debug-unaligned.apk
  • GradleAndroidFlavorExample-cuttlefish-release-unsigned.apk

が生成されます。

さらに、ビルドタイプも指定出来ます。

$ gradlew assembleSquidDebug

この場合、

  • GradleAndroidFlavorExample-squid-debug-unaligned.apk

が生成されます。

$ gradlew build

で、全て(mainも含む)のフレーバー、ビルドタイプがビルドされます。

サンプルプロジェクト

https://github.com/nowsprinting/GradleAndroidFlavorExample に置きました

参考資料

*1:細かくは未検証