Android Studio 0.4.0 への移行
Android Studio 0.4.0 がリリースされていますね! わー、ぱちぱち。
Android Studio 0.4.0 への移行は、単にバージョンを上げるだけという感じではなかったので、苦労した箇所などを簡単にメモしておきます。
Gradle と Android Gradle プラグインのバージョンアップ
Android 0.4.0 では、Gradle 1.9、Android Gradle プラグイン 0.7 が必要となっています。 それぞれバージョンアップを行いましょう。 Gradle は Gradle ラッパーとしてプロジェクト内に持っていることが多いと思うので、gradle/wrapper/gradle-wrapper.properties を次のように書きかえればいいはずです。 *1
-distributionUrl=http\://services.gradle.org/distributions/gradle-1.8-bin.zip +distributionUrl=http\://services.gradle.org/distributions/gradle-1.9-bin.zip
Android Gradle プラグインのバージョンアップは、build.gradle の記述を次のような感じで変更すればよいですね。 (0.7.1 がリリースされており、後述する packagingOptions の exclude は 0.7.1 から使えるようになったものなので、バージョンは 0.7.1 以降を指定しています。)
buildscript { repositories { mavenCentral() } dependencies { - classpath 'com.android.tools.build:gradle:0.6.+' + classpath 'com.android.tools.build:gradle:0.7.1+'
build.gradle の記述変更
Android Gradle プラグイン 0.7 では、大きめの変更が入っていますので、そのままビルドしようとしても失敗する可能性があります。 とりあえずビルドしてみて、エラーが出たら必要に応じて変更を加えればよいでしょう。
以下に、私が行った変更を書いておきます。
buildConfig
から buildConfigField
に変更
Android Gradle プラグイン 0.6.x のときには、BuildConfig
クラスのフィールドを定義するために、次のように buildConfig
メソッドを使用することができました。
android {
buildTypes {
release {
buildConfig "public final static boolean XXX_TEST_MODE = false;"
}
0.7.0 以降ではこれは使用できなくなっており、代わりに buildConfigField
メソッドを使用します。 buildConfigField
は 3 引数をとるメソッドで、前から順にフィールドの型、フィールドの識別子、フィールドの値を設定します。
android { buildTypes { release { buildConfigField "boolean", "XXX_TEST_MODE", "false" }
私がはまったところ
私はもともと次のようなビルドスクリプトを書いていました。
android { buildTypes { debug { buildConfig "public final static boolean XXX_TEST_MODE = false;" } testtarget.initWith(buildTypes.debug) testtarget { buildConfig "public final static boolean XXX_TEST_MODE = true;" }
で、Android Gradle プラグイン 0.6.x の頃までは問題なくビルドできていたのですが、0.7.1 に移行して次のように書きかえるとビルドできなくなりました。
android { buildTypes { debug { buildConfigField "boolean", "XXX_TEST_MODE", "false" } testtarget.initWith(buildTypes.debug) testtarget { buildConfigField "boolean", "XXX_TEST_MODE", "true" }
ビルドに失敗する際のエラー出力は次のようなもの。
.../BuildConfig.java:14: エラー: 変数 XXX_TEST_MODEはすでにクラス BuildConfigで定義されています public static final boolean XXX_TEST_MODE = true; ^
debug
ビルドタイプでの buildConfigField
の設定がそのまま testtarget
に受け継がれて、testtarget
ビルドタイプでも同名のフィールドを定義しているので問題が起こる、という感じでした。 で、どうすればいいのか結構悩んだのですが、単に debug
ビルドタイプで buildConfigField
メソッドを呼び出す前に initWith
して testtarget
ビルドタイプの初期化をしてやれば良いのでした。
android { buildTypes { // `initWith` した後に `debug` ビルドタイプで `buildConfigField` 呼び出しをすればよい testtarget.initWith(buildTypes.debug) debug { buildConfigField "boolean", "XXX_TEST_MODE", "false" } testtarget { buildConfigField "boolean", "XXX_TEST_MODE", "true" }
jar ファイルに含まれるリソースファイルがだぶる問題
ビルドを実行すると次のようなエラーが発生するかもしれません。 これは、libs ディレクトリの JAR ファイルを展開したときに、同じパスのリソースファイルが複数の JAR ファイルに存在すると発生するエラーのようです。
Error: duplicate files during packaging of APK ...\build\apk\App-testtarget-unaligned.apk Path in archive: META-INF/NOTICE.txt Origin 1: ...\App\libs\xxxx-4.0.0.jar Origin 2: ...\App\libs\yyyy-4.0.0.jar You can ignore those files in your build.gradle: android { packagingOptions { exclude 'META-INF/NOTICE.txt' } }
どちらの JAR に含まれるリソースファイルも必要でない場合 (例えばパッケージに含めなくて良い NOTICE.txt など) は、そのリソースファイルをパッケージング時に除外するようにすることでこのエラーを回避できます。 エラーメッセージにも書かれていますが、次のようなコードを書けばよいです。
android { packagingOptions { exclude 'META-INF/NOTICE.txt' } }
これは Android Gradle プラグインの 0.7.1 で導入された機能です。
lint でエラーになってもビルドに失敗しないようにする
おそらく Android Gradle プラグインの 0.7.0 からだと思うのですが、build
タスクの一部として lint
タスクも実行されるようになりました。 で、デフォルトでは lint
タスクでエラーが発生するとビルドが止まるようになっています。 理想的には lint
でエラーが発生しないようにするのが良いと思いますが、実際には問題ない箇所でも lint のエラーになることがあった *2 ので、とりあえず lint でエラーが出てもビルドを継続するようにしました。
android {
lintOptions {
abortOnError false
}
- Lint に関する設定のユーザーガイド: Gradle Plugin User Guide - Android Tools Project Site
参考資料
- New Build System - Android Tools Project Site : Android Gradle プラグインのバージョンごとの変更点が書かれています
Android Studio 0.4.0 移行とは関係ないけど Windows で Gradle を使うときの文字コードではまった
Android Studio 0.4 移行とは関係ないのですが、Windows で Gradle を使っていると、行コメントの次の行までコメント扱いされる、ということがあってはまってしまいました。
Groovy 処理系が期待するファイルの文字エンコーディング (Windows なので CP932) と、実際のファイルの文字エンコーディング (UTF-8) が違っているために起こる問題のようです。 この問題については下記の記事が参考になりました。
- コメントに何を書いてもいい」と思うのは、/**/については正しいが、//については正しくない - uehaj's blog
- groovyでスクリプトのエンコーディングを指定する - uehaj's blog
- GradleでAndroidアプリをビルドする « androidnote
結局のところ、Gradle ラッパーを使っているのであれば、gradlew.bat を次のように変更したら良さそうですね。 *3
diff --git a/gradlew.bat b/gradlew.bat index 8a0b282..c56f988 100644 --- a/gradlew.bat +++ b/gradlew.bat @@ -10,6 +10,7 @@ if "%OS%"=="Windows_NT" setlocal @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. set DEFAULT_JVM_OPTS= +set JAVA_OPTS="-Dgroovy.source.encoding=UTF-8" "-Dfile.encoding=UTF-8" set DIRNAME=%~dp0 if "%DIRNAME%" == "" set DIRNAME=.
コンソール出力のエンコーディングも変化してしまうことに気付いた (追記)
-Dfile.encoding によるデフォルトファイルエンコーディングの変更を行うと、コンソール出力のエンコーディングも変化してしまうことに気付きました。 いまのところビルドスクリプトのエンコーディングを指定するいい方法はなさそうですね。
次の記事に、Gradle に変更を加えてビルドスクリプトのエンコーディングを指定できるようにすることについて書きました。