Android Gradle Plugin 入門

androidstudio

最近、俗にいうネイティブアプリの流れが社内で、巻き起こっているので
改めて Android Studioで使うGradleの説明をしていきたいと思います。

去年の「Android Advent Calendar 2013」で 「Gradleことはじめ」という記事を書きました

もう、いまさら新規のAndroid開発環境において、Eclipse + antを使いはじめる人は居ないと思いますが
当時は、Android開発においてのスタンダードがEclipse + antでした。

もう、Eclipseなんていう負の遺産は捨てて、Android Studioに移行しましょう。

Android Studioの良さは、今回は語り尽くせないので、他の方の記事を参考してください

では、今回のブログの趣旨である、Android Gradle Pluginを説明していきます

僕の考えた最強で平凡なbuild.gradle

androidgradle

細かい説明の前に、全体像はこんな感じになります。

buid.gradle

buildscript {  
    repositories {
        jcenter()
    }
    dependencies {
        classpath 'com.android.tools.build:gradle:0.12.+'
    }
}

allprojects {  
    repositories {
        jcenter()
    }
    tasks.withType(JavaCompile) {
        options.encoding = 'UTF-8'
    }
}

apply plugin: 'com.android.application'

def VERSION_CODE = 1  
def VERSION_NAME = "1.0.0"  
def PACKAGE_NAME = "jp.wasabeef.gradle"

android {  
    compileSdkVersion 20
    buildToolsVersion "20.0.0"
    useOldManifestMerger false

    defaultConfig {
        minSdkVersion 14
        targetSdkVersion 20
        versionCode VERSION_CODE
        versionName VERSION_NAME
    }

    packagingOptions {
        exclude 'META-INF/NOTICE.txt'
        exclude 'META-INF/LICENSE.txt'
        exclude 'META-INF/DEPENDENCIES'
        exclude 'META-INF/NOTICE'
        exclude 'META-INF/LICENSE'
    }

    signingConfigs {
        debug {
        }
        release {
            // @See gradle.properties
            // productKeyStore=../wasabeef.keystore
            // productKeyAlias=wasabeef
            // productKeyStorePassword=wasabeef
            // productKeyAliasPassword=wasabeef

            storeFile file(productKeyStore)
            keyAlias productKeyAlias
            storePassword productKeyStorePassword
            keyPassword productKeyAliasPassword
        }
    }

    buildTypes {
        debug {
            debuggable true
            zipAlign true
            applicationIdSuffix ".debug"
        }
        release {
            debuggable false
            zipAlign true
            runProguard true
            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
            signingConfig signingConfigs.release
        }
    }

    productFlavors {
        develop {
            applicationId "${PACKAGE_NAME}.develop"
        }
        staging {
            applicationId "${PACKAGE_NAME}.staging"
        }
        production {
            applicationId PACKAGE_NAME
        }
    }

    compileOptions {
        sourceCompatibility JavaVersion.VERSION_1_7
        targetCompatibility JavaVersion.VERSION_1_7
    }
}

repositories {  
    maven { url "https://repo.commonsware.com.s3.amazonaws.com" }
}

dependencies {  
    // compile fileTree(dir: 'libs', include: ['*.jar'])
    compile 'com.android.support:support-v4:20.+'
    compile 'com.android.support:support-v13:20.+'
    compile 'com.google.android.gms:play-services:4.+'
    compile 'com.squareup:otto:1.3.+'
    compile 'com.squareup.okhttp:okhttp:2.0.+'
    compile 'com.squareup.picasso:picasso:2.3.+'
    compile 'com.squareup.okhttp:okhttp-urlconnection:2.0.+'
    compile 'com.jakewharton:butterknife:5.1.+'
    compile 'com.jakewharton.timber:timber:2.4.+'
    compile 'com.fasterxml.jackson.core:jackson-core:2.2.+'
    compile 'com.fasterxml.jackson.core:jackson-databind:2.2.+'
    compile 'com.commonsware.cwac:richedit:0.3.0'
}

記述内容の説明

1. buildscript

ビルドスクリプト自体に依存関係がある場合などに
Pluginのdependenciesを登録しておきます
Androidの開発では、Android Gradle Pluginが必要となります

buildscript {  
    repositories {
        // 最近は、Maven Centralではなく、BintaryのjCenterを指定するのが一般的に
        jcenter()
    }
    dependencies {
        // Android StudioのVersionによって、Required Versionが異なります
        // バージョンを"+"で省略すると、常に最新のVersionを取得します
        classpath 'com.android.tools.build:gradle:0.12.+'
    }
}

2. allprojects

Android Studio及びGradleはマルチプロジェクトに対応しているので
ルートプロジェクトを含む全プロジェクトに適用されます

allprojects {  
    repositories {
        jcenter()
    }
    tasks.withType(JavaCompile) {
        // EncodeをUTF-8にしときます
        options.encoding = 'UTF-8'
    }
}

3. apply plugin

Android Gradle Pluginの適用をします

apply plugin: 'com.android.application'  

4. def

groovyの書き方になりますが、変数を定義します

def VERSION_CODE = 1  
def VERSION_NAME = "1.0.0"  
def PACKAGE_NAME = "jp.wasabeef.gradle"  

5. android { }

Android Gradle Pluginでは、android {} ブロックに設定を書いていきます

android {  
    // 省略
}

6. Target

アプリをビルド時に利用される SDK及びToolのVersionを指定します
Android SDK Managerで最新をチェックして、出来るだけ最新を保ちましょう
チームで開発するときは、チームで同じVersionがインストールされてる必要があります

android {  
    compileSdkVersion 20
    buildToolsVersion "20.0.0"
}

7. Manifest Merger

設定値をfalseにすることで AndroidManifestに決められた変数が使えるようになりました
例えば、後述するProduct Flavorsでパッケージ名をビルド時に決定するときに
AndroidManifestには、ビルド時に決定されたパッケージ名を使うことが出来ます

exp.
${applicationId} : パッケージ名の変数

android {  
    useOldManifestMerger false
}

8. Default Config

主に、Google PlayやAndroid Platform側が必要とするアプリのVersion設定

android {  
    defaultConfig {
        // 最低動作 Version (API Level)
        minSdkVersion 14

        // 開発時のテスト済みであるVersionの指定
        // これより新しいVersionが出た場合でも
        // Android Platform側のデフォルト設定を出来るだけ変えないようにしてくれる
        targetSdkVersion 20

        // Google Playが識別するためのVersion
        versionCode VERSION_CODE    // 1

        // アプリの利用者に触れることのある一般的なアプリのバージョン名
        versionName VERSION_NAME    // "1.0.0"
    }
}

9. Packaging Options

Androidアプリ開発において、複数のLibraryが利用されるときに
META-INF内のFileがConflictするので、excludeしないとビルドが通らない場合があるため
必要なときに必要なものの除外をいれときます

android {  
    packagingOptions {
        exclude 'META-INF/NOTICE.txt'
        exclude 'META-INF/LICENSE.txt'
        exclude 'META-INF/DEPENDENCIES'
        exclude 'META-INF/NOTICE'
        exclude 'META-INF/LICENSE'
    }
}

10. Signing Configs

アプリファイル(.apk)を作成するときに必要となるKeystoreの設定
Debug用や、Release用のConfigを用意しておきます

android {  
    signingConfigs {
        debug {
        }
        release {
            // gradle.propertiesにプロパティとして以下のように定義しておきます
            // productKeyStore=../wasabeef.keystore
            // productKeyAlias=wasabeef
            // productKeyStorePassword=wasabeef
            // productKeyAliasPassword=wasabeef

            storeFile file(productKeyStore)
            keyAlias productKeyAlias
            storePassword productKeyStorePassword
            keyPassword productKeyAliasPassword
        }
    }
}

11. Build Types

アプリファイル(.apk)を作成するときに必要となる設定値の定義

android {  
    buildTypes {
        // debugビルド時に有効
        debug {
            // デバッグモード許可
            debuggable true
            // .apkの[最適化](http://qiita.com/kazuqqfp/items/8eae69e309c6ed75d661)
            zipAlign true
            // パッケージ名につけるサフィックス     -> "jp.wasabeef.gradle.debug"
            applicationIdSuffix ".debug"
            // Version名につけるサフィックス
            versionNameSuffix '-dev'            -> "1.0.0-dev"
        }
        release {
            // デバッグモード禁止
            debuggable false
            // .apkの[最適化](http://qiita.com/kazuqqfp/items/8eae69e309c6ed75d661)
            zipAlign true
            // ソースコードの難読化
            runProguard true
            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'

            // signingConfigsで定義したKeystoreの設定を利用
            signingConfig signingConfigs.release
        }
    }
}

12. Product Flavors

Android Gradle Pluginで最もCoolなプロダクトフレーバー
接続先の切り替えや、パッケージ名の変更、またはResourcesの変更をすることができます

android {  
    productFlavors {
        develop {
            applicationId "${PACKAGE_NAME}.develop"
        }
        staging {
            applicationId "${PACKAGE_NAME}.staging"
        }
        production {
            applicationId PACKAGE_NAME
        }
    }
}

13. Compile Options

利用するJavaのVersionを指定

android {  
    compileOptions {
        sourceCompatibility JavaVersion.VERSION_1_7
        targetCompatibility JavaVersion.VERSION_1_7
    }
}

14. Repositories

プロジェクト内で利用するMaven Repositoryを指定します

repositories {  
    maven { url "https://repo.commonsware.com.s3.amazonaws.com" }
}

15. Dependencies

コード上で、依存しているLibraryを記述します
Mavenと同じで、Meven CentralやjCenterから自動的に取得します

  • antには出来ない
dependencies {  
    // compile fileTree(dir: 'libs', include: ['*.jar'])
    compile 'com.android.support:support-v4:20.+'
    compile 'com.android.support:support-v13:20.+'
    compile 'com.google.android.gms:play-services:4.+'
    compile 'com.squareup:otto:1.3.+'
    compile 'com.squareup.okhttp:okhttp:2.0.+'
    compile 'com.squareup.picasso:picasso:2.3.+'
    compile 'com.squareup.okhttp:okhttp-urlconnection:2.0.+'
    compile 'com.jakewharton:butterknife:5.1.+'
    compile 'com.jakewharton.timber:timber:2.4.+'
    compile 'com.fasterxml.jackson.core:jackson-core:2.2.+'
    compile 'com.fasterxml.jackson.core:jackson-databind:2.2.+'
    compile 'com.commonsware.cwac:richedit:0.3.0'
}

16. BuildConfig.java

Gradleでビルドした結果としてBuildConfig.javaが自動生成される
コード上で、接続環境先の判定やデバッグモードの状態判定や、VersionをUserAgentに利用するときなどに
static変数なので、便利に利用することができます。

/**
 * Automatically generated file. DO NOT MODIFY
 */
package jp.wasabeef.gradle;

public final class BuildConfig {  
  public static final boolean DEBUG = false;
  public static final String PACKAGE_NAME = "jp.wasabeef.gradle";
  public static final String BUILD_TYPE = "release";
  public static final String FLAVOR = "develop";
  public static final int VERSION_CODE = 1;
  public static final String VERSION_NAME = "1.0.0";
}

独自設定を入れたい場合はbuildConfigFieldを使って、設定を追加することもできます

android {  
    productFlavors {
        develop {
            applicationId "${PACKAGE_NAME}.develop"

            def gitSha = 'git rev-parse --short HEAD'.execute([], project.rootDir).text.trim()
            buildConfigField "String", "GIT_SHA", "\"${gitSha}\""
        }
    }
}

雑感

Android Gradle Pluginだけじゃなくて、他にもGradleのpluginがたくさんあるので
それらを利用することで、もっとCoolなbuild.gradleができると思います

ここで書いた設定は、基本的にProduct開発において最低減必要な 設定になりますので
参考にしてもらえたらと思います。

by @wasabeef_jp