後編にあたる今回は、Gradleのビルドスクリプトbuild.gradle
を中心に、あんなこといいな、できたらいいなというTIPSを紹介します(と言ってもできないことが多いです)。 今回紹介するTIPSのほとんどがバッドノウハウのカタマリです。Android StudioがEarly Access Previewであるため致し方無いことですが、開発が進むにつれ、ちょっとでも改善されていくことを願ってます。
Android StudioとGradleの小難しい関係
どうして前後編にもわたる話を長々と説明するハメになったかというと、Android StudioがビルドをGradleに委譲してしまったために尽きます。ビルドをAndroid StudioやEclipseなどの特定のIDEに依存せず、Gradleに一本化したことで、IDEからもコマンドラインからも同じ手順でビルドできる利点がありますが、Android Studioの連係がスムーズではないため、今のところデメリットのほうが強調されてしまっています。
たとえば、Android Studioが作成したプロジェクトにはGradleのコマンド(gradlewとgradlew.bat)も付属しており、JDKとAndroid SDKさえあれば、どこでもビルドができる配慮がされています(図2)。
特定のIDEに依存せずにビルドできる発想はすばらしいのですが、まだ実装が追いついていないため、現状ではGradle(Android Gradleプラグイン)とAndroid StudioのProject Structureの両方を熟知してないと困ることが多いです。けれど、そんな人は多くはいませんよね……。
Android Studioでできること・できないこと
【注意】今回紹介した内容はAndroid Studio v0.1.2で確認しました(もう少しで原稿ができあがるという時にAndroid Studio v0.1.3がリリースされたので、v0.1.3での違いを追補として載せておきます)。
Android Studioのプロジェクトを扱う上で、よく躓きそうな点をTIPS集としてまとめてみました。Android Studioだけでは解決できず、コマンドラインからGradleを使う場合もありますが、その時は、プロジェクトに付属しているgradlew / gradlew.bat
コマンドを用いることとします。
予備知識として、Android Studioが使うGradleとコマンドラインgradlew
が使うGradleの関係をおさえておきましょう(図3)。
どちらもGradle本体(<HOME>/.gradle
)は同じものを使っているのですが、呼び出し方法の違いから若干の差異が出てきます。
[TIPS#1]ときおりヘンなダイアログが出るんですが、OK押していいんですか?
Android Studioでプロジェクトを開いたときに図4のようなダイアログが出てくることがあります。
「Gradleの構造から外れた Module なんで、Projectから削除してよいか?」と聞いているんですが、間違っても「OK」を押さないでください。押すと無慈悲にもModuleの定義ファイル(*.iml)が削除されてしまいます(図5)
Android Studioが何を検知してこのダイアログを表示しているのかわかっていませんが、build.gradle
を修正した後にこのダイアログが出てくる傾向があるようです。気を利かせているつもりなのですが、かなり破壊的な事をしでかすので、このことはよく覚えておいてください。
それでも、間違って「OK」ボタンを押してしまった場合は、図6のようにメニューバーから「File → Import Module...」を選び、<PROJECT_HOME>/build.gradle
をインポートすることで復活が可能です。
なにより、このダイアログが出る理由は何なんでしょうかね。バグですかね? 最近見なくなったので、解決済みの不具合なのかもしれません。
[TIPS#2]プロジェクトにライブラリを追加したいんですが、どうしたらいいんですか
Android Studioが推奨したいのは、このどちらなのかわかりませんが、大きく2通りのやり方があります。どの方法もbuild.gradle
にライブラリの記述をすることは変わりありません。
その1:build.gradleに設定した内容をAndroid Studioに自動反映させる
すでに登録済みのandroid-support-v4.jar
と同じように、<PROJECT_HOME>/MyFirstApp/libs
に追加したいライブラリ(Jarファイル)を配置してbuild.gradle
にその旨を記述します(リスト1)。
リスト1のようにbuild.gradle
を修正し、<PROJECT_HOME>/MyFirstApp/libs
ディレクトリにライブラリを配置した後、該当プロジェクトを開き直します(メニューバーの「File → Close Project」で閉じて開き直すのが便利です)。すると、しばらく何かを処理したかと思うと、指定したJarファイルが図7のようにAndroid Studioのライブラリとして認識されます(Android Studioに認識されるとJarファイルに三角のアイコンが付きます)。
GradleはMavenやIvyのようにネット上のリポジトリからライブラリをダウンロードする機能があるのですが、その方法でもライブラリを追加することができます(リスト2)。
冒頭の3行はMavenリポジトリからライブラリをダウンロードするためのおまじないです。こちらも先ほどと同じように、build.gradle
を修正してから、プロジェクトを開き直すとJarファイルのダウンロードを行い、ライブラリとしてプロジェクトに追加します。ダウンロード方式の場合、Jarファイルはプロジェクトの外(<HOME>/.gradle
)にあるため、図8のようにAndroid Studioでは外部ライブラリ(External Library)として認識されます。
Jarファイルはインターネット上のMavenリポジトリからダウンロードしてくるので、職場のPCなどファイアーウォール内で作業する場合は、第2回で示したようにAndroid Studioにプロキシ設定を行っておいてください。
Gradle自体にもプロキシの設定があります。Android Studio経由でGradleを実行する場合は、Android Studioのプロキシ設定が引き継がれるようですが、コマンドラインからGradleを利用する場合は、その限りではありません。コマンドラインからGradleを利用する事もあるので、念のためGradleのプロキシ設定も行っておきましょう。
Gradleのプロキシ設定は、GradleのUser Guideにあるように <HOME>/.gradle/gradle.properties
に対して行います。リスト3はgradle.properties
にプロキシ設定を行った例です。
設定の優先度は、以下の通りでした。
gradle.properties
>「Preferences / HTTP Proxy」
build.gradle
を変更するたびにプロジェクトを開き直すのが煩わしいのですが、一応この方法でAndroid Studioの設定に反映させることができます。「一応」と付けたのにはワケがありまして、v0.1.2で試した限りでは次のような問題がありました。
- testCompile、runtimeなどのスコープ指定が効かない(無視される)
- GradleのUser GuideによるとMavenのようにライブラリのスコープを設定できるのですが、
compile
以外の指定があるとAndroid Studioへの自動反映がうまくできませんでした。
- build.gradleからライブラリ指定を削除してもAndroid Studioに反映されない
- ライブラリの追加はできますが、
build.gradle
から特定のライブラリを削除しても、そのことはAndroid Studioに反映されませんでした(削除されずに残ります)。ライブラリのバージョンを変更した場合も同様に、Android Studioでは以前の設定が残り、違うバージョンのライブラリが新規追加されるだけでした。
一見うまく行ってそうですが、このような問題がいろいろあるようです。ちなみに、上記のような状況になった場合は「Project Structre / Libraries」から該当ライブラリを直接削除すれば良いです。
その2:build.gradleに設定した内容とは別に、Android Studioに手動で設定する
これまで紹介した方法はbuild.gradle
さえ修正すればAndroid Studioに自動的に反映されますが、正直煩わしい点が多いです。現状、それほどAndroid Studioとの連係がスムーズではないので、こんな割り切った方法もあります。
build.gradle
はリスト4のように設定して、<PROJECT_HOME>/MyFirstApp/libs
にある*.jarファイルをすべてライブラリの対象とします。
当然、この設定ではAndroid Studioは自動でbuild.gradle
のライブラリ指定を認識しないため、別途「libsディレクトリはライブラリの置き場所」であることを設定します。このライブラリの設定方法は幾通りかあります。
- 「Project Structure / Modules / Dependencies」で「Module用ライブラリ」として登録
- 「Project Structure / Libraries」で「Project用ライブラリ」として登録してから、Moduleに設定
- Projectツールウィンドウで指定したディレクトリ(やJarファイル)を「Module用ライブラリ」として登録
- etc...
一番簡単なProjectツールウィンドウからの登録方法を図13に示しておきます。
「Project用ライブラリ」と異なり「Module用ライブラリ」に識別する名前は要りません。すでに登録済みの「android-support-v4.jar」はそのまま残していても邪魔にはなりませんが、気になるなら削除しておきましょう。
[TIPS#3]コンパイルエラーが表示されません
Windows版Android Studioで明らかにエラーのあるソースコードをビルドしてみても、ビルド結果が表示されるのMessagesツールウィンドウに詳細なエラーメッセージが表示されません。
ちなみにですが、Mac版のAndroid Studioでは上記のようなことにはならず、普通にエラーメッセージが表示されます。
なかなか致命的な感じがしますが、どうもWindows版Android Studioの制限のようです。コンパイルエラーを知りたい場合は、コマンドラインからgradlew build
を実行するか、Android Studioのエディタが指摘する問題を確認するくらいしか無さそうです(Android Studio v0.1.3でも試してみましたが、まだ解決していませんでした)。
余談ですが、プログラマ向けQ&AサイトのStack Overflowに次のようなQ&Aがあります。
回答に『「Preferences / Compiler / Use external build」を無効にすればよい』とありますが、この方法はオススメしません。この機能を無効にすると、GradleではなくAndroid Studio自体(つまりはIntelliJベース)のビルダーが有効になります。たしかにコンパイルエラーが表示されるようにはなりますが、Android Studioが目指しているGradleビルダーが動かなくなるため、それ以外の不都合が生じました(たとえば、R.java
が更新されなくなるなどです)。
極論を言えば「User external build」を無効にするのであれば、素直にIntelliJを使った方が良いです。
[TIPS#4]build.gradleの編集にコード補完が効きません
一見、補完が効いているように見えますが、すでに記述しているキーワードを補完候補にあげているだけで、build.gradle
の文脈に応じた補完は行っていません。
Android Studio(のベースであるIntelliJ)はコード補完の的確さが売りのひとつなだけに、早くbuild.gradle
のコード補完がサポートされることを望みます。
IntelliJを知っている人たちの中に「GroovyプラグインのGDSLで何とかなるのでは?」と思った人もいるでしょう。
しかし、IntelliJもAndroid Studioもまだbuild.gradle
用のGDSLをプリセットしていません。インターネットを探すと自作のbuild.gdsl
を公開している人もいますが、それでもbuild.gradle
を編集するのに十分とは言えませんでした。いずれ、今よりはマシな補完機能がつくと思いますので、気長に待ちましょう。
[TIPS#5]Gradleのタスクを実行したいんですけど、どうしたらいいんでしょう?
どういうわけか、Android StudioからGradleの任意のタスクを実行できないようです。v0.1.2まではメニューバーの「Build -> Rebuild Project」を行ってもgradlew clean
は実行されませんでした。
v0.1.3からは「Rebuild Project」を実行すると gradlew clean assemble
相当のことをするようになりました。それでも、それ以外のタスクを実行する手段はありません。結局のところコマンドラインからGradleを実行するのが確実な方法と言えます。
Windows版のAndroid Studioに限った話ですが、外部ツール(External Tools)にコマンドプロンプト(cmd.exe
)を登録することで、ちょっとだけ得した気分を味わえます。図19のように「Preferences / External Tools」でコマンドプロンプトを登録します。
表1 「Edit Tool」ダイアログの入力値
項目 | 値 |
Name | cmd
|
Options | "Synchronize files after execution"と"Open console"にチェック |
Show in | "Main menu"にチェック |
Program | C:\Windows\System32\cmd.exe |
Working directory | $ProjectFileDir$ |
メニューバーの「Tools」内に登録したコマンド名「cmd」が表れますので、それを実行します。
すると、図21のようにRunツールウィンドウ内にコマンドプロンプトが張り付きますので、そこで gradlew
などのコマンドを実行できます。
Mac版で同様のこと(/bin/bash
を登録してみる)を試してみましたが、プロンプトが表示されないなど、使いやすいものではありませんでした。Mac版やLinux版の場合は、ターミナルをExternal Toolsに登録してラウンチャー代わりに使うのがせいぜいかと思います。
ちなみに、Android Studio v0.1.3から、IntelliJにあった「Gradleツールウィンドウ」が復活しました。まだ何のタスクも表示されませんでしが、アップデートが進めば、ここからGradleのタスクを実行できるのでは?と期待が膨らみます。
[TIPS#6]Javaのソースコードに日本語を入れたらエラーになりました
WindowsやMac(でJDK6を使ったとき)に起こる問題です。筆者が試したところ、Android Studio上で問題になったのを見かけなかったのですが、コマンドラインからGradleを実行した場合は100%再現しました。
これは文字エンコードにまつわる問題でして、Android Studioのエディタは標準で「UTF-8」に設定されていますが、コンパイルに用いるJDKは何も指定しないとプラットフォームのデフォルトエンコードが設定されます。つまり「UTF-8のソースコードを、Windows-31Jと思ってコンパイルにかける」ため、ソースコードに日本語が含まれるとエラーになるわけです。
解決方法は大きく2通りあります。
- ソースコードをUTF-8ではなく、プラットフォームのデフォルトエンコードに合わせる
- ビルドスクリプトなどにソースコードのエンコードを明示する
前者はちょっと身もフタもない解決策ですが「開発環境がWindowsのみ」など制約条件が成り立つなら、それほど悪い策とは思っていません。ただ、Android開発のセオリーとしてUTF-8以外のソースコードを用いるのが良いのかどうかはわかりませんが……。
後者の場合、その情報をどこに指定するかで、何通りか選択肢がありますが、筆者はリスト5のようにビルドスクリプトにエンコードを明示する方法を好みます。
build.gradle
に指定する以外にも<HOME>/.gradle/gradle.properties
や環境変数JAVA_OPTS
にfile.encoding
を指定する方法があります。こちらの設定は「ソースコードのエンコード」ではなく「デフォルトエンコード」を暗黙的に変更することになります。筆者としては「ソースコードのエンコードはビルドの情報の一部で、ビルドスクリプトに明示するのが正しい」と思っているので、こちらのやり方は好みません。
[TIPS#7]build.gradle に日本語のコメントを入れたらエラーになりました
ビルドスクリプトもいろいろ設定を追加すればコメントを書きたくなると思うのですが、こちらも先ほどのJavaのソースコードと同じく、デフォルトエンコードの影響を受けます。
こちらもJavaのソースコードと同様に、
build.gradle
をプラットフォームのデフォルトエンコードに合わせる
build.gradle
のエンコードを明示する
の2通りの対策が考えられますが、Javaのソースコードと異なり後者の対応が簡単ではありません。なるべくエンコード設定の範囲を狭めたいと思ったのですが、コマンドライン、Android Studioの両方で有効だったのは環境変数JAVA_OPTS
を使う方法でした。
表2 build.gradleのエンコードの指定箇所
エンコードの指定箇所 | Android Studio | コマンドライン |
<HOME>/.gradle/gradle.properties に設定 | 無効 | 有効 |
環境変数JAVA_OPTS に設定 | 有効 | 有効 |
このいずれの方法も「build.gradle
のエンコード指定」ではなく「デフォルトエンコードを強制的に変更する」という意味にあたります。この設定をしてしまうと、先ほど紹介した「Javaのソースコードのエンコード指定」も軒並み影響を受けるため、個人的には身もフタも無いやり方だと思っています。build.gradle
に対するスマートなエンコード指定があって欲しいものです(なおGroovyスクリプトのエンコード指定であるgroovy.source.encoding
はGradleには有効ではないようです)。
このあたりの詳細についてはJGGUGのuehajさんが自身のブログで説明されています。
この説明で言及のあった3つの解決策のうち、最後の1つがGradleで日本語コメントを使う妥協点なのでは?と思いました。
教訓は、デフォルトエンコーディングとスクリプトのエンコーディングが異なるなら(1)文字コード変換するか(2)実行時に正しくencodingを指定せよ (3)スクリプトのコメントについて文字コードなんてこまけーこたあ良いんだよ、といいたい場合は、/**/を推奨。(or行末に空白でも入れとけ)
コメントに何を書いてもいい」と思うのは、/**/については正しいが、//については正しくない - uehaj's blog
つまりは、図27のようなコメントスタイルを用いた方が良いのでは?という話です。
「行コメントの後に空白を入れておく」のは、エディタの設定で『不要な空白を除去する』事が可能なため推奨しません。
[TIPS#8]Android Studioに「Gradleの割り当てメモリが足りない」と怒られます
このエラーはWindowsで32bit JVMを使っている場合に見かけます(Mac版では見かけたことがありません)。どうもAndroid Studioが内部で実行しているGradleに割り当てているメモリが 1024MB(-Xmx1024m)であることが起因しているようです(<AS_SYSTEM>/log/idea.log
で確認できます)。
これを回避するために<HOME>/.gradle/gradle.properties
にリスト7のような設定を追加します。
[TIPS#9]インクリメンタルビルドは無いの?
無いです。
そもそもインクリメンタルビルドはEclipse固有の特徴で、これがあるからEclipseを使っているという人もいるほどです。多少、情報に詳しい人は「IntelliJもver12から自動ビルドが付いたでしょ?」と思われるかもしれません。
Android Studioのビルドが「Gradleベースになった」という罠がここにもありまして、たしかにAndroid Studioにも「Preferences / Compiler」に「Make project automatically」という項目がありますが、これを有効にしても自動ビルド(インクリメンタルビルド)は有効になりません。
なにより、この「Preferences / Compiler」の設定画面そのものがほとんど意味を持たないと思っていた方がよいでしょう。「Preferences / Compiler / Android DX Compiler」といういかにもな設定画面も同様です。
まとめ
ここまで読んで「あぁ、しばらくAndroid Studio使うの止めた」と思った人も少なからずいると思います。そこはやっぱりEAP(Early Access Preview)ですので、そう判断するのも正解のひとつではないでしょうか。
Android Studioがv0.1~v0.1.3までにアップデートを繰り返したのを見て、気付いたことはこの2点です。
- 本気でビルドをGradleベース(
build.gradle
が原本)にしようとしている
- Project Structureを何とかして
build.gradle
と連携させようとしている
Android Studioが開発中でGradleとの連係がままならない中で、ちょっとでも凝ったビルドをしようと思うと、GradleおよびAndroid Studioの両方に対して深い知識が必要になります。Android Studio側に至っては推理力も必要で、ややもすればAndroid Studioのソースを追いかけないと困ることもありました。さすがに、そこまで来ると本末転倒も甚だしいなと思い、すんでの所で留まりましたが……。
不毛だなと思う反面、Android StudioとGradle連係部分は未開の地であるため、先駆者になれるチャンスが埋まっています。我こそはと思う方には、ぜひこの荒野を開拓していって欲しいと願うばかりです。
前後編に分けて説明したAndroid StudioとGradle連係については、これでおしまいとします。次回からは、Android Studioが(IntelliJから受け継いで)もともと備えている便利な機能について説明していきます。
おまけ
本文中に細切れで紹介していたbuild.gradle
やgradle.properties
の完全なリストを載せておきます。