Android Gradle Plugin 0.12 → 0.13の変更点

  • 21
    いいね
  • 0
    コメント
この記事は最終更新日から1年以上が経過しています。

Android Gradle Plugin 0.13が9月にリリースされて2週間以上が経ち、既に記事を書かれている方もいらっしゃるので今更なのですが、個人的に重要と思う箇所があり0.12 → 0.13の変更点について詳細に確認してみました。
http://tools.android.com/tech-docs/new-build-system

対象は、現時点でリリースされている0.13.0から0.13.2までです。

実際の動作等は部分的にしか確認できていませんので、ご了承ください。
※伝聞調の書き方の部分は未確認と思ってください
※後日アップデートするかもしれません

0.13.0の変更点

Gradle 2.1以上が必要

これまでGradle 1.10+が必要でしたが、これではもう動かなくなりました。
Gradleラッパー(gradlew)を使っている場合は、gradle/wrapper/gradle.propertiesdistributionUrlのバージョン部分を以下のように2.1に修正する必要があります。

gradle.properties
distributionUrl=http\://services.gradle.org/distributions/gradle-2.1-all.zip

build.gradleに独自のスクリプトを書いている場合は、Gradle 2.1で使えなくなるものがないか確認する必要があるかもしれません。

テストアプリでAndroidManifestが定義可能に

テストアプリといっているのはconnectedAndroidTestなどのタスクで動かすInstrumentationTestCaseなどのことですが、これまでは Plugin がテスト用のManifestを自動生成していたため、独自の設定を入れたりすることができませんでした。
これは特にライブラリ開発の場合に重要です。

UIライブラリなどでは実際のActivityに組込んで動かさなければほとんどテストできないため、Activityから利用するテストケースを書きたくなりますが、Activityを呼び出すにはAndroidManifest<activity>の定義を書かなければなりません。
今まで、Android Gradle Pluginでのテストではこうした設定が書けなかったため、以下のような方法をとるしかありませんでした。

  • Activityを使わなくてもできる部分だけをテストする
  • テスト用のアプリを別プロジェクトとして用意してテストする
  • (ライブラリにテスト用のActivityを組込む)

例えば、パッケージcom.exampleをテストするActivityを使って以下のようにテストケースを書くとします。

java
package com.example.test;
:
public class ActivityTest extends ActivityInstrumentationTestCase2<DemoActivity> {

    private DemoActivity activity;

    public ActivityTest() {
        super(DemoActivity.class);
    }

    @Override
    protected void setUp() throws Exception {
        super.setUp();
        setActivityInitialTouchMode(true);
        activity = getActivity();
    }

この場合、AndroidManifestに以下のような定義を書く必要があり、今までは書いても無視されていたのですが0.13で取り込まれるようになりました。
(つまり、テスト専用のActivityを用意してライブラリをテストすることができます)

<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.example.test">

    <application>
        <uses-library android:name="android.test.runner" />
        <activity android:name=".DemoActivity" />
    </application>

</manifest>

<instrumentation>は自動的に追加されます。

※この変更のおかげで、自分のUIライブラリの場合はJaCoCoによるカバレッジ計測で10%程度だったものが95%以上までカバーできるようになりました。

Android Studioでの注意点

現時点のBeta 0.8.6はこの仕組みに対応していないため、少々問題があります。

テスト用のR.javaが生成されない

テストアプリのpackageは末尾に.testがつく別アプリの位置づけになるため、R.javaは本体とは別になりますが、0.8.6ではこれがビルドされません。
Android Studioで認識させるには、一度コマンドラインで./gradlew connectedCheckなどでビルドする必要があります。
現時点のBeta Channelで配布されているAndroid Studio 0.8.9では解消しています。

テスト用AndroidManiest内のURIやActivity名が認識されない

以下のように赤字になってしまいますが、動作上は問題ないです。
これはAndroid Studio 0.8.9でも、Canary Channel最新の0.8.11でも未解決のようです。

Screenshot 2014-10-05 15.29.36.png

AndroidManifestの placeholder が Build Types でも設定可能に

AndroidManifestにおけるplaceholderというのは、Android Gradle Plugin 0.11で導入された(はずの)ものです。
AndroidManifest内に${xxx}の形式で記述しておき、build.gradleでその値を決定するものです。
例えば以下のように書いておき、ActivityのラベルをProduct Flavorごとに変えることができます。

build.gradle
    defaultConfig {
        applicationId "com.example"
        :
        manifestPlaceholders = [ activityLabelMain: "Example" ]
    }
    productFlavors {
        free {
            applicationId "com.example.free"
            manifestPlaceholders = [ activityLabelMain: "Example free" ]
        }
        pro {
            manifestPlaceholders = [ activityLabelMain: "Example pro" ]
        }
    }
AndroidManifest.xml
        <activity
            android:name=".MainActivity"
            android:label="${activityLabelMain}" >

上記では、installFreeDebugでインストールするとExample FreeinstallProDebugでインストールするとExample Proのラベルが表示されます。

これまでこの機能はProduct Flavorで利用可能でしたが、Build Typeでも使えるようになったようです。
同じ例を使うと、例えば以下のようにBuild Typeをラベルにくっつけることができます。

build.gradle
    defaultConfig {
        applicationId "com.example"
        :
        manifestPlaceholders = [ activityLabelMain: "Example" ]
    }
    productFlavors {
        free {
            applicationId "com.example.free"
            manifestPlaceholders = [ activityLabelMain: "Example free" ]
        }
        pro {
            manifestPlaceholders = [ activityLabelMain: "Example pro" ]
        }
    }
    buildTypes {
        // debugビルドのみ末尾に debug を付与
        debug {
            manifestPlaceholders = [ activityLabelSuffix: " debug" ]
        }
        release {
            :
            manifestPlaceholders = [ activityLabelSuffix: "" ]
        }
    }
AndroidManifest.xml
        <activity
            android:name=".MainActivity"
            android:label="${activityLabelMain}${activityLabelSuffix}" >

上記でビルドすると、ラベルは以下のようになります。

  • installFreeDebugExample Free debug
  • installFreeReleaseExample Free
  • installProDebugExample Pro debug
  • installProDReleaseExample Pro

ライブラリのAndroidManifestでplaceholderを定義可能に

ライブラリでも上記のplaceholderが利用できるようになったようです。
ライブラリ内で未解決のplaceholderは利用アプリ側で解決させることもできるようです。
(未確認です)

Variant.getMappingFile()でProGuardマッピングファイルが参照可能に

ProGuardを実行すると、難読化前後の名称のマッピングファイルが生成されますが、このファイルにbuild.gradleからアクセスできるようになったということのようです。

例えば、以下のようにすると、ProGuardをかけたVariantではマッピングファイルのオブジェクト(File)が取得できていることが分かります。

build.gradle
android {
    :
    productFlavors {
        free {
            :
        }
        pro {
            :
        }
    }
    buildTypes {
        debug {
            :
        }
        release {
            runProguard true
            :
        }
    }
    :
}

afterEvaluate { ->
    android.applicationVariants.each { variant ->
        println "mapping: ${variant.name}: ${variant.getMappingFile()?.path}"
    }
}
$ ./gradlew assemble
mapping: freeDebug: null
mapping: freeRelease: /xxx/app/build/outputs/proguard/free/release/mapping.txt
mapping: proDebug: null
mapping: proRelease: /xxx/app/build/outputs/proguard/pro/release/mapping.txt
:app:preBuild
:

※Issueとしては下記がありますが、アップデートがないため使い方等はよく分かりませんでした。
https://code.google.com/p/android/issues/detail?id=73737

DensityとABIでの複数APKへのSplitメカニズムを導入

詳細はApk Splitsにあります。
(未確認です)

バグ修正

(未確認です)

0.13.1の変更点

テスト用のManifestで<instrumentation>をマージできるように

上述のテスト用AndroidManifestでの<instrumentation>を自分で書いた場合にもマージされるようになったようです。
(未確認です)

uninstallAllタスクの修正

0.13.0で発生した不具合の修正のようです。
./gradlew uninstallAllを実行するとエラーが発生するようになっていたようです。
https://code.google.com/p/android/issues/detail?id=76388

設定不備があるとVariantが出力されずGradleの評価が失敗する問題を修正

(未確認です)

テストがない場合にconnectedCheckが失敗するように

これまではテストケースのないプロジェクトではconnectedCheckconnectedAndroidTestタスクを呼び出しても何事もなく通過していましたが、0.13.1ではテストケース(テストケースクラス)が一つもないとタスクが失敗するようになりました。

Screenshot 2014-10-05 15.40.40.png

テストが全くないプロジェクトで(テストでなくlint等を動かしたいために)取りあえずタスクを通過させるには、androidTest/javaディレクトリ以下に何らかのテストケースクラスを作ればOKです。

0.13.2の変更点

manifest mergerが不正な<uses-sdk>を追加するのを修正

0.13.1で発生した不具合の修正のようです。
下記のIssueなどでレポートされており、AndroidManifestのマージにより<uses-sdk>が複数出力されてしまう問題があったようです。
https://code.google.com/p/android/issues/detail?id=76612

補足

Issueは以下で検索して確認しています。
https://code.google.com/p/android/issues/list?can=1&q=label%3ASubcomponent-Tools-gradle&colspec=ID+Type+Status+Owner+Summary+Stars&cells=tiles