Picture

Hi, I'm ogaclejapan.

Android Software Engineer at AbemaTV

Androidの新ビルドツール「Android Gradle Plugin」その2

前回の続きを書くの巻。

Gradleビルド設定のカスタマイズ

Androidプラグインでは次のManifest情報をビルド時に書き換えることができる。

  • minSdkVersion
  • targetSdkVersion
  • versionCode
  • versionName
  • packageName
  • Package Name for the test application
  • Insturument test runner

android { defaultConfig { ... } }に定義すると環境毎の設定デフォルト値として適用される。

def getVersionName() {
    ...
}

android {
    compileSdkVersion 15

    defaultConfig {
        versionCode 12
        versionName getVersionName()
        minSdkVersion 16
        targetSdkVersion 16
    }
}

プロパティを定義してないときのDSL上の値とデフォルト値は次のとおり。

Property Name Default value in DSL object Default value
versionCode -1 Manifestファイルの値
versionName null Manifestファイルの値
minSdkVersion -1 Manifestファイルの値
targetSdkVersion -1 Manifestファイルの値
packageName null Manifestファイルの値
testPackageName null app package name + “.test”
testInstrumentationRunner null android.test.InstrumentationTestRunner
signingConfig null null
proguardFile N/A N/A
proguardFiles N/A N/A

ビルド環境のカスタマイズ

デフォルトでアプリケーションをdebug,releaseビルドするためのビルド設定を自動的に設定する。
Androidのプラグインはこれら2つの環境をカスタマイズするだけでなく、独自のビルド環境を作成することができる。

android {
    buildTypes {
        // (1)
        debug {
            packageNameSuffix ".debug"
        }

        // (2)
        jnidebug.initWith(buildTypes.debug)

        // (3)
        jnidebug {
            packageNameSuffix ".jnidebug"
            jnidebugBuild true
        }
    }
}
  1. debug { ... } はdebug環境に関するビルド設定を定義できる
  2. debugビルドの設定をベースに独自のビルド設定を作成する(これでjnidebugという新しい環境を定義できる)
  3. jnidebug { ... } はjnidebugという独自環境に関するビルド設定を定義できる

ビルド環境に関するデフォルト設定値は次のとおり。
debugとreleaseのデフォルト値が異なるようので要注意。

Property Name Default value for debug Default value for release / other
debuggable -true false
jniDebugBuild -false false
renderscriptDebugBuild -false false
renderscriptOptimLevel -3 3
packageNameSuffix -null null
versionNameSuffix -null null
signingConfig android.signingConfigs.debug null
zipAlign false true
runProguard false true
proguardFile N/A N/A
proguardFiles N/A N/A

独自のビルド環境を定義することで環境に依存したコードやリソースをビルドに含めることができる。
デフォルトではsourceSetにsrc/<buildtypename>/として自動で設定される。
なお、他のsourceSetと同様にsetRoot('path')で格納先を変更することもできるようになっている。

android {
    sourceSets.jnidebug.setRoot('foo/jnidebug')
}

また、独自のビルド環境を定義すると、新しいassemble<buildtypename>タスクも自動で作成される。
これはAndroidプラグインに組み込まれているdebug,release環境のタスクと同様に利用することができる。

独自のビルド環境に定義したコードやリソースはビルド時、次のように適用される

  • AndroidManifestファイルはmainに定義してあるものにマージされる
  • ソースコードはコードを含むフォルダがソースフォルダの1つとしてコンパイル対象に含まれる
  • リソースはmainに定義してあるものを上書きする

証明書の設定

Androidプラグインではアプリケーションの署名に必要な項目をandroid { signingConfigs {...} }に定義する。
なお、debug環境用のビルド設定には$HOME/.android/debug.keystoreを使用するように自動的に設定されている。

android {
    signingConfigs {

        debug {
            storeFile file("debug.keystore")
        }

        myConfig {
            storeFile file("other.keystore")
            storePassword "android"
            keyAlias "androiddebugkey"
            keyPassword "android"
        }
    }

    buildTypes {
        foo {
            debuggable true
            jniDebugBuild true
            signingConfig signingConfigs.myConfig
        }
    }
}

debugキーストアはデフォルトの$HOME/.android/debug.keystoreが設定されているときのみ自動で生成される。
それ以外の場所に変更している場合は自動で生成されないので事前に自分で作成しておくこと。

ProGuardの設定

バージョン0.4からProGuard(version:4.9)がサポートされている。
ProGuardのプラグインはAndroidプラグインが自動的にロードしているので、runProguardプロパティが有効なら自動でタスクに組み込まれて実行されるようになっている。

android {
    buildTypes {
        release {
            runProguard true
            proguardFile getDefaultProguardFile('proguard-android.txt')
        }
    }

    productFlavors {
        flavor1 {
        }
        flavor2 {
            proguardFile 'some-other-rules.txt'
        }
    }
}

マルチプロジェクトの設定

Gradleではマルチプロジェクト構成もサポートしている。

例えば、次のような構成のプロジェクトがある場合、
プロジェクトルート直下にsettings.gradleファイルを置き、各プロジェクト内にbuild.gradleファイルを置く。

MyProject
└ app
└ libraries
  └ lib1 
  └ lib2

Gradleでは各プロジェクトのフォルダ階層を:に表現した名前を一意なIDとして使用する。
settings.gradleにはこの各GradleプロジェクトのIDを定義すればよい。

include ':app', ':libraries:lib1', ':libraries:lib2'

appプロジェクトがlib1プロジェクトに依存している場合は、appプロジェクトのbuild.gradleに依存を定義すればよい。

dependencies {
    compile project(':libraries:lib1')
}

ライブラリプロジェクトの設定

AndroidのリソースやAPIを使用するライブラリを開発する場合にはAndroidライブラリプロジェクトとして作成する。
Gradleのビルド設定は基本的にAndroidプロジェクトと同様だが、apply pluginの部分をandroid-libraryと定義する必要があることに注意すること。

buildscript {
    repositories {
        mavenCentral()
    }

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

apply plugin: 'android-library'

android {
    compileSdkVersion 15
}

LibraryプロジェクトはAndroidプロジェクトと違い、apkは生成されない。
代わりにAndroid標準の.aarパッケージを生成する。

また、ビルド環境に関してもAndroidプラグイン標準で組み込まれているdebug,releaseのみが使用可能となっている。

テストの設定

GradleのAndroidプロジェクトではテストビルドを組み込んでいるので、従来のようにテストプロジェクトを別途用意する必要がない。

次の2つのパラメータはテスト用に予め用意されている。

  • testPackageName
  • testInstrumentationRunner

テスト結果のレポートは単一プロジェクトであればbuild/reports/instrumentTestsに出力される。
出力場所を変更したい場合にはandroid { testOptions { ... } }reportDirプロパティを定義すればよい。

android {
    ...

    testOptions {
        reportDir = "$project.buildDir/foo/report"
    }
}

ビルドタスクのカスタマイズ

実際のプロジェクトでは「コンパイル時にxxの処理を実行したい」とか、特定のタスクをフックしたい思うことがある。
Androidプラグインではタスクを内容を書き換えたり、依存を加えたりできるようなポイントが用意されている。

作成するプロジェクトタイプにより、使用できるプロパティは異なるがandroidオブジェクトには次の3つが定義されている。

  • applicationVariants (アプリケーションを生成するプロジェクトでのみ利用可能)
  • libraryVariants (ライブラリプロジェクトでのみ利用可能)
  • testVariants (上記両方のプロジェクトで利用可能)

applicationVariantsにアクセスするには以下のように記述するばよい。

android.applicationVariants.each { variant ->
    ....
}

従って、(未だ実装されていない)ネイティブ共有ライブラリsoファイルをapkに含めるhack処理は新バージョンだと次のように書くこともできる。

task copyNativeLibs(type: Copy) {
    def libsDir = "$projectDir/libs"
    from(libsDir) { include '**/*.so' }
    into new File(buildDir, 'native-libs')
}

tasks.clean.dependsOn 'cleanCopyNativeLibs'

android.applicationVariants.each { variant ->
    variant.javaCompile.dependsOn copyNativeLibs
    variant.packageApplication.jniDir new File(buildDir, 'native-libs')
}

うん、前よりステキになった(・∀・)

まとめ

0.2系の時代からだと、proguardが実装されたり、タスクのフック処理が簡単になったりと0.4系にあげるメリットは結構あると思われる。
欲を言えば、soファイルあたりは早く正式に実装してもらいたいところだが…。

現状ではEclipseがIDEレベルでAndroidのGradleビルドをサポートしていないので、
当面はUnitテストやapk生成の自動化用途で活躍することになるだろう。

あー早くAndroidStudio流行らないかな−(´・ω・`)

一応最新版のbuild.gradleテンプレを作成したのでGistにあげておく。

Back to Top