有名なAndroid オープンソースアプリ2つのbuild.gradleを読む

他の人のbuild.gradleは知見の塊ですよね。。
ただのメモですが割と組み込めそうなものが多く面白かったです。

## Google I/Oアプリ iosched
build.gradle
https://github.com/google/iosched/blob/master/android/build.gradle

### BuildConfigにフィールド追加
以下のようにBuildConfigクラスにフィールド追加している

```groovy
android {

    defaultConfig {
        buildConfigField("boolean", "ENABLE_DEBUG_TOOLS", "false")
```

buildTypesでデバッグ時のみENABLE_DEBUG_TOOLSをtrueにするなどの切り替えを行っているようです

```groovy

    buildTypes {
        debug {
            debuggable true
            minifyEnabled false
            signingConfig signingConfigs.debug
            buildConfigField("boolean", "ENABLE_DEBUG_TOOLS", "true")
```

### デバッグのkeystoreは固定する(複数人で開発していてapk入れなおすときに便利)
署名が違うとアンインストールして入れなおさないといけないので入れておくと地味に便利ですね

```groovy
signingConfigs {
        debug {
            storeFile file("../android/debug.keystore")
```

### apkから除外
apkを作るときに中に入れないファイルの拡張子を指定するようです(apkがapkの中に入らないようにしている？？)

```groovy
    aaptOptions {
        noCompress 'apk'
    }
```

### ユニットテストで実装されていないメソッドを呼ぶとクラッシュするのを予防する
テストの時に実装していないメソッドを呼ぶと通常はExceptionだけど、デフォルトの値を返してくれるようにしてくれるらしい。

```groovy
    // Test Android jar comes with unimplemented methods that throw exceptions by default. This
    // option forces the methods to return default values instead. Required for static methods,
    // such as TextUtils, as those cannot be mocked with Mockito.
    // Refer http://tools.android.com/tech-docs/unit-testing-support#TOC-Method-...-not-mocked.-
    testOptions {
        unitTests.returnDefaultValues = true
    }
```

こちらに記載がありました http://qiita.com/numa08/items/7ee78a0f29a4bc728f48 

### バージョンはrootのgradle.propertiesに持っていく
rootのbuild.gradleで宣言して使う方法は知っていたのですが、こっちのほうがシンプルで便利そうですね。

```groovy

dependencies {

    // Google Play services split client libs.
    compile "com.google.android.gms:play-services-analytics:${google_play_services_client_library_version}"
```

https://github.com/google/iosched/blob/master/gradle.properties

```groovy
android_support_lib_version = 23.0.1
google_play_services_client_library_version = 7.0.0
```

### デバッグとリリースの中間のビルドタイプを作成する
リリース前にプロガードをかけて実際に動かしてみると、
ビルドできなかったり、JavaScriptInterfaceのメソッドが呼ばれなかったりして、困ったことありませんか？
`qualityassurance`というビルドタイプを用意していて、プロガードは行うけど、デバッグ可能というビルドタイプを作っているようです。JavaScriptInterfaceを入れたり、新しいライブラリに依存する際はこれを使ってデバッグしてみると良いかもしれません。

```groovy
    buildTypes {
        debug {
            debuggable true
            minifyEnabled false
            signingConfig signingConfigs.debug
            buildConfigField("boolean", "ENABLE_DEBUG_TOOLS", "true")
            buildConfigField("String", "SERVER_MANIFEST_ENDPOINT", "\"${production_api_manifest_endpoint}\"")
            // 省略
        }
        qualityassurance {
            debuggable true
            minifyEnabled true
            signingConfig signingConfigs.debug
            proguardFiles getDefaultProguardFile('proguard-android.txt'), file('proguard-project.txt')
            buildConfigField("boolean", "ENABLE_DEBUG_TOOLS", "true")
            buildConfigField("String", "SERVER_MANIFEST_ENDPOINT", "\"${production_api_manifest_endpoint}\"")
            // 省略
        }
        release {
            debuggable false
            minifyEnabled true
            // No signing config as we do this separately.
            proguardFiles getDefaultProguardFile('proguard-android.txt'), file('proguard-project.txt')
            buildConfigField("String", "SERVER_MANIFEST_ENDPOINT", "\"${production_api_manifest_endpoint}\"")
            // 省略
        }
    }
```

## u2020
https://github.com/JakeWharton/u2020
Jake神のサンプルアプリ
build.gradle
https://github.com/JakeWharton/u2020/blob/master/build.gradle
通常androidはマルチプロジェクト構成(rootプロジェクトの下にappプロジェクトがある感じ)にしますが、Jakeのサンプルは1プロジェクト構成のようです。シンプルで分かりやすいですね

### バージョンコードとバージョンネームを自動的につける
以下のようにやっているようです。ただそれぞれの番号は手動で変更しているっぽいです

```groovy
// Manifest version information!
def versionMajor = 1
def versionMinor = 0
def versionPatch = 0
def versionBuild = 0 // bump for dogfood builds, public betas, etc.
android {
  defaultConfig {
    versionCode versionMajor * 10000 + versionMinor * 1000 + versionPatch * 100 + versionBuild
    versionName "${versionMajor}.${versionMinor}.${versionPatch}"
...
```

### gitのリビジョン番号とビルド時間をアプリに組み込む
バグが再現した時などに便利そうですね

```groovy
def gitSha = 'git rev-parse --short HEAD'.execute([], project.rootDir).text.trim()
def buildTime = new Date().format("yyyy-MM-dd'T'HH:mm:ss'Z'", TimeZone.getTimeZone("UTC"))

android {
  defaultConfig {
    buildConfigField "String", "GIT_SHA", "\"${gitSha}\""
    buildConfigField "String", "BUILD_TIME", "\"${buildTime}\""
```

### CIかどうか判定してpreDexLibrariesを無効化する
サーバーで実行する場合はこのオプションを無効にしたほうが速いらしいです。
また大抵のCIサーバーはこの環境変数が入っているっぽいですね。
http://tools.android.com/tech-docs/new-build-system/tips#TOC-Improving-Build-Server-performance.

```groovy
def isCi = "true".equals(System.getenv("CI"))
def preDexEnabled = "true".equals(System.getProperty("pre-dex", "true"))

android {
  dexOptions {
    // Skip pre-dexing when running on Travis CI or when disabled via -Dpre-dex=false.
    preDexLibraries = preDexEnabled && !isCi
  }
```

### lint Optionで特定のものを禁止にする 

禁止にしたいものがあれば便利そうですね
また`textOutput 'stdout'`で標準出力に出してくれるようです。
http://apdr.qiniudn.com/com.android.build.gradle.internal.dsl.LintOptions.html#com.android.build.gradle.internal.dsl.LintOptions:textOutput

```groovy
  lintOptions {
    textReport true
    textOutput 'stdout'
    fatal 'UnusedResources'
    warning 'ResourceType' //TODO remove eventually with ButterKnife 8.0 release
  }
```

### 依存関係の解決時にバージョンを強制する？
よく分かっていませんが、そういうことができるようです。
https://docs.gradle.org/current/dsl/org.gradle.api.artifacts.ResolutionStrategy.html

```groovy
configurations.all {
  resolutionStrategy {
    force 'com.android.support:support-annotations:23.1.1'
  }
}
```

### ライセンス
google/iosched
https://github.com/google/iosched/blob/master/LICENSE.txt
JakeWharton/u2020
https://github.com/JakeWharton/u2020/blob/master/LICENSE.txt