Migration to Android Plugin for 3.0

Android Studio 3.0のリリース

Android Studio 3.0がリリースされて数ヶ月経ちました。
ようやくつい最近少し触ったので、メモ程度に。
公式ドキュメントにGradle Pluginの移行についてのHow toがあるので、英語みてわかる人はこっち見た方が早いです。
いっつも公式ドキュメントの英語が瞬時に理解できないのは、自分の英語力なのか、技術力なのか、はたまた両方なのかって感じですね。

こういう人にオススメ

Android Studio 3.0に移行したい、かつ以下のような状態が一つでもある。

  • プロジェクト内に複数モジュールがある
  • ビルドを速くしたい
  • Product FlavorとBuild Typeの組分けが必要
  • Content Providerをビルドバリアントに対応したい。

Gradle Pluginの更新(導入)

プラグインのバージョン3.0はGradleバージョン4.1未満では動きません。
まずは、gradle-wrapper.properties、project rootのbuild.gradleにそれぞれ以下を追加

distributionUrl=https\://services.gradle.org/distributions/gradle-4.1-all.zip
buildscript {
    repositories {
        // You need to add the following repository to download the new plugin.
        google()
    }

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

Configure Build Variants

新しい概念がいくつかあります。
が、自分に一旦必要だったFlavor Dimension, Fallbackだけ書きます。

上記を考えるために以下のような具体例を考えましょう。

1. Flavorを複数持つ

  • 日本版とグローバル版のアプリを同じワンソースで開発している。

2. Build Typeを複数持つ

  • 本番・開発・QA配信環境をそれぞれ分ける。

このような状況は普通にAndroidアプリを開発していれば、特に違和感ないと思います。

そして、以前までのGradle Pluginのバージョンでは、少し問題がありました。

Build Type(であるべき)のプロパティがFlavor依存になっていることです。 (あるべきっていうのは少し誤解があるかもしれません。)

今までのGradle Pluginの問題点は、minSdkVersion, applicationId, manifestHolderなどの属性を変更するために、
新しいFlavorを追加する必要があり、結果的にFlavorの数が激増してしまうことです。

上記のような問題を解決するのが、Flavor DimensionとFallbackです。

Flavor Dimension

まずは、コードで。

android { 
  // Step1
    flavorDimensions "applicationId", "minSdkVersion"

    // Step2 
    productFlavors {
        minApi18 {
            // Step3
            dimension "minSdkVersion"
     // Step4
            minSdkVersion 24
        }
        minApi15 {
            dimension "minSdkVersion"
            minSdkVersion 15
        }
        us {
            dimension "applicationId"
            applicationId "com.bison.sampleapp"
        }
        japan {
            dimension "applicationId"
            applicationId "jp.co.bison.sampleapp"
        }
    }
} 

Dimension(applicationIdとminSdkVersion)を追加することで、各Flavorは必ず、Dimensionの属性を指定することが必須になりました。
なので、Dimensionを指定すれば、必ずその該当moduleの各Flavorにはその属性を機械的に指定してあげてください。

これにより、FlavorのDimensionの組み合わせが可能になりました。 上記の場合だと、ビルドバリアントのoutputとして、usMinApi15YourBuildTypejapanMinApi24YourBuildType などが可能になりました。

手順をさくっと説明すると

Step1: Product Flavorのプロパティに依存する属性(applicationId, minSdkVersion)を決める。
Step2: 上記より分ける項目を追加(us, japan, minApi15, minApi18)
Step3: 各Flavorにdimensionを追加。
Step4: プロパティを追加

サンプルコードもあげてます。

Fallback

Fallbackという概念があります。
戻すとか元の状態にするみたいな意味です。

これはmoduleごとのBuild Typeの冗長性を排除します。

app moduleでは、Build Typeとしてrelease, staging, debugと3種類必要だけど、他のmoduleにおいては、
releaseとdebug(もしくは一つ)で十分なことがあったりします。

以前までは、app moduleに以下のように書く必要がありました。

// app build.gradle
dependencies {
    // appのdebugコンパイル時には、bison moduleのusDebugを参照する
    debugCompile project(path: ':bison', configuration: 'usDebug')
}

appのmodule側で直接bisonのmoduleのビルドバリアントを指定する形です。
また、app側からusMinApi15DebugCompileなどと、より詳細に指定することも可能です。
が、めちゃくちゃ数が増えるので面倒くさいです。

これからはこう書きましょう。

dependencies{
    implementation project(':bison')
}

Gradleはapp moduleのビルドバリアントを、他の依存しているmoduleにも適用しようとします。

ただ、他のmoduleに関しては、特にProduct Flavorを区別する必要がなく(us, japan不要)、
Build Type(release, staging, debug)のみ変更したい場合があります。

その場合はProduct Flavorには何も書かなければ問題なしです。
もちろん書けば、そのFlavorが適用されます。(各moduleでもDimensionは必須です。)

さらに言うと、stagingも必要ない場合があります。(debugとreleaseだけでよい場合)
その場合は、appのbuild.gradleに以下のように書いてください。

buildTypes {
    staging{
        // appからの他のmoduleにstagingのBuild Typeを探しに行く場合、
        // 他のmoduleにはstagingが存在しないので、debugを適用してあげる。
        matchingFallbacks = ['debug']
    } 
}

おまけ

上記試した際に、ContentProviderの重複エラーが生じることがありますが、
それはAndroidで複数Product Flavorを利用するに書いています。

以上です。