Android Studio最速入門~効率的にコーディングするための使い方

第6回Android StudioとGradle[後編]

後編にあたる今回は、Gradleのビルドスクリプトbuild.gradleを中心に、あんなこといいな、できたらいいなというTIPSを紹介します(と言ってもできないことが多いです⁠⁠。 今回紹介するTIPSのほとんどがバッドノウハウのカタマリです。Android StudioがEarly Access Previewであるため致し方無いことですが、開発が進むにつれ、ちょっとでも改善されていくことを願ってます。

Android StudioとGradleの小難しい関係

どうして前後編にもわたる話を長々と説明するハメになったかというと、Android StudioがビルドをGradleに委譲してしまったために尽きます。ビルドをAndroid StudioやEclipseなどの特定のIDEに依存せず、Gradleに一本化したことで、IDEからもコマンドラインからも同じ手順でビルドできる利点がありますが、Android Studioの連係がスムーズではないため、今のところデメリットのほうが強調されてしまっています。

図1 Android StudioとGradleの関係
図1

たとえば、Android Studioが作成したプロジェクトにはGradleのコマンド(gradlewとgradlew.bat)も付属しており、JDKとAndroid SDKさえあれば、どこでもビルドができる配慮がされています図2⁠。

図2 Android Studioが作成したプロジェクトにはGradleが含まれている
図2

特定のIDEに依存せずにビルドできる発想はすばらしいのですが、まだ実装が追いついていないため、現状ではGradleAndroid 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⁠。

図3 GradleのコマンドラインとAndroid Studioの関係
図3

どちらもGradle本体<HOME>/.gradleは同じものを使っているのですが、呼び出し方法の違いから若干の差異が出てきます。

[TIPS#1]ときおりヘンなダイアログが出るんですが、OK押していいんですか?

Android Studioでプロジェクトを開いたときに図4のようなダイアログが出てくることがあります。

図4 ⁠Import Gradle Projects」ダイアログ
図4

「Gradleの構造から外れた Module なんで、Projectから削除してよいか?」と聞いているんですが、間違っても「OK」を押さないでください。押すと無慈悲にもModuleの定義ファイル(*.iml)が削除されてしまいます図5

図5 うっかり「OK」を押してModuleが削除されたProject
図5

Android Studioが何を検知してこのダイアログを表示しているのかわかっていませんが、build.gradleを修正した後にこのダイアログが出てくる傾向があるようです。気を利かせているつもりなのですが、かなり破壊的な事をしでかすので、このことはよく覚えておいてください。

それでも、間違って「OK」ボタンを押してしまった場合は、図6のようにメニューバーから「File → Import Module...」を選び、<PROJECT_HOME>/build.gradleをインポートすることで復活が可能です。

図6 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へのライブラリ追加の記述(ローカル参照)
dependencies {
  compile files('libs/android-support-v4.jar')
  compile files('libs/gson-2.2.4.jar')
}

リスト1のようにbuild.gradleを修正し、<PROJECT_HOME>/MyFirstApp/libsディレクトリにライブラリを配置した後、該当プロジェクトを開き直します(メニューバーの「File → Close Project」で閉じて開き直すのが便利です⁠⁠。すると、しばらく何かを処理したかと思うと、指定したJarファイルが図7のようにAndroid Studioのライブラリとして認識されます(Android Studioに認識されるとJarファイルに三角のアイコンが付きます⁠⁠。

図7 ライブラリの自動認識(ローカル参照:クリックすると動きがわかります)

GradleはMavenIvyのようにネット上のリポジトリからライブラリをダウンロードする機能があるのですが、その方法でもライブラリを追加することができますリスト2⁠。

リスト2 build.gradleへのライブラリ追加の記述(ダウンロード方式)
repositories {
  mavenCentral()
}

dependencies {
  compile files('libs/android-support-v4.jar')
  compile 'com.google.code.gson:gson:2.2.4'     // <-- here!!
}

冒頭の3行はMavenリポジトリからライブラリをダウンロードするためのおまじないです。こちらも先ほどと同じように、build.gradleを修正してから、プロジェクトを開き直すとJarファイルのダウンロードを行い、ライブラリとしてプロジェクトに追加します。ダウンロード方式の場合、Jarファイルはプロジェクトの外<HOME>/.gradleにあるため、図8のようにAndroid Studioでは外部ライブラリ(External Library)として認識されます。

図8 ライブラリの自動認識(ダウンロード方式:クリックすると動きがわかります)

Jarファイルはインターネット上のMavenリポジトリからダウンロードしてくるので、職場のPCなどファイアーウォール内で作業する場合は、第2回で示したようにAndroid Studioにプロキシ設定を行っておいてください。

Gradle自体にもプロキシの設定があります。Android Studio経由でGradleを実行する場合は、Android Studioのプロキシ設定が引き継がれるようですが、コマンドラインからGradleを利用する場合は、その限りではありません。コマンドラインからGradleを利用する事もあるので、念のためGradleのプロキシ設定も行っておきましょう。

Gradleのプロキシ設定は、GradleのUser Guideにあるように <HOME>/.gradle/gradle.properties に対して行います。リスト3gradle.propertiesにプロキシ設定を行った例です。

リスト3 <HOME>/.gradle/gradle.properties
systemProp.http.proxyHost=proxy.example.com
systemProp.http.proxyPort=8080

設定の優先度は、以下の通りでした。

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ファイルをすべてライブラリの対象とします。

リスト4 build.gradleの修正点
dependencies {
  compile fileTree(dir: 'libs', include: '*.jar')
}

当然、この設定ではAndroid Studioは自動でbuild.gradleのライブラリ指定を認識しないため、別途「libsディレクトリはライブラリの置き場所」であることを設定します。このライブラリの設定方法は幾通りかあります。

  • 「Project Structure / Modules / Dependencies」「Module用ライブラリ」として登録
  • 「Project Structure / Libraries」「Project用ライブラリ」として登録してから、Moduleに設定
  • Projectツールウィンドウで指定したディレクトリ(やJarファイル)「Module用ライブラリ」として登録
  • etc...

一番簡単なProjectツールウィンドウからの登録方法を図13に示しておきます。

図13 コンテキストメニュー「Add as Library...」でライブラリを追加(クリックすると動きがわかります)

「Project用ライブラリ」と異なり「Module用ライブラリ」に識別する名前は要りません。すでに登録済みの「android-support-v4.jar」はそのまま残していても邪魔にはなりませんが、気になるなら削除しておきましょう。

[TIPS#3]コンパイルエラーが表示されません

Windows版Android Studioで明らかにエラーのあるソースコードをビルドしてみても、ビルド結果が表示されるのMessagesツールウィンドウに詳細なエラーメッセージが表示されません。

図15 Windows版Android Studioではコンパイルエラーが表示されない
図15

ちなみにですが、Mac版のAndroid Studioでは上記のようなことにはならず、普通にエラーメッセージが表示されます。

図16 Mac版Android Studioではコンパイルエラーが表示される
図16

なかなか致命的な感じがしますが、どうも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の文脈に応じた補完は行っていません。

図18 build.gradleのコード補完の例
図18
あまり意味のない補完候補を出す(むしろ有害なのでは?)

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」でコマンドプロンプトを登録します。

図19 ⁠Settings / External Tools」にコマンドプロンプトを登録
図19
表1 ⁠Edit Tool」ダイアログの入力値
項目
Namecmd
Options"Synchronize files after execution"と"Open console"にチェック
Show in"Main menu"にチェック
ProgramC:\Windows\System32\cmd.exe
Working directory$ProjectFileDir$

メニューバーの「Tools」内に登録したコマンド名「cmd」が表れますので、それを実行します。

図20 メニューバー「Tools→cmd」でコマンドプロンプトを実行
図20

すると、図21のようにRunツールウィンドウ内にコマンドプロンプトが張り付きますので、そこで gradlewなどのコマンドを実行できます。

図21 Runツールウィンドウにコマンドプロンプトが張り付く(クリックすると動きがわかります)

Mac版で同様のこと/bin/bashを登録してみる)を試してみましたが、プロンプトが表示されないなど、使いやすいものではありませんでした。Mac版やLinux版の場合は、ターミナルをExternal Toolsに登録してラウンチャー代わりに使うのがせいぜいかと思います。

ちなみに、Android Studio v0.1.3から、IntelliJにあった「Gradleツールウィンドウ」が復活しました。まだ何のタスクも表示されませんでしが、アップデートが進めば、ここからGradleのタスクを実行できるのでは?と期待が膨らみます。

図22 まだ何も表示されないGradleツールウィンドウ(v0.1.3)
図22

[TIPS#6]Javaのソースコードに日本語を入れたらエラーになりました

図23 日本語を含むJavaのソースコード
図23

WindowsやMac(でJDK6を使ったとき)に起こる問題です。筆者が試したところ、Android Studio上で問題になったのを見かけなかったのですが、コマンドラインからGradleを実行した場合は100%再現しました。

図24 コマンドラインからGradleでビルド(Windows:クリックすると動きがわかります)
図25 コマンドラインからGradleでビルド(Mac&JDK6:クリックすると動きがわかります)

これは文字エンコードにまつわる問題でして、Android Studioのエディタは標準で「UTF-8」に設定されていますが、コンパイルに用いるJDKは何も指定しないとプラットフォームのデフォルトエンコードが設定されます。つまり「UTF-8のソースコードを、Windows-31Jと思ってコンパイルにかける」ため、ソースコードに日本語が含まれるとエラーになるわけです。

解決方法は大きく2通りあります。

  • ソースコードをUTF-8ではなく、プラットフォームのデフォルトエンコードに合わせる
  • ビルドスクリプトなどにソースコードのエンコードを明示する

前者はちょっと身もフタもない解決策ですが「開発環境がWindowsのみ」など制約条件が成り立つなら、それほど悪い策とは思っていません。ただ、Android開発のセオリーとしてUTF-8以外のソースコードを用いるのが良いのかどうかはわかりませんが……。

後者の場合、その情報をどこに指定するかで、何通りか選択肢がありますが、筆者はリスト5のようにビルドスクリプトにエンコードを明示する方法を好みます。

リスト5 <PROJECT_HOME>/MyFirstApp/build.gradleの一部
tasks.withType(Compile) {
  options.encoding = 'UTF-8'
}

build.gradleに指定する以外にも<HOME>/.gradle/gradle.propertiesや環境変数JAVA_OPTSfile.encodingを指定する方法があります。こちらの設定は「ソースコードのエンコード」ではなく「デフォルトエンコード」を暗黙的に変更することになります。筆者としては「ソースコードのエンコードはビルドの情報の一部で、ビルドスクリプトに明示するのが正しい」と思っているので、こちらのやり方は好みません。

 Android Studioのプロジェクトに対するエンコード設定は「Preferences / File Encoding」で行いますが、build.gradleとは連動していないようです。ここの設定は、Android Studioのエディタに対してのみ有効な設定と思った方がよさそうです。

[TIPS#7]build.gradle に日本語のコメントを入れたらエラーになりました

ビルドスクリプトもいろいろ設定を追加すればコメントを書きたくなると思うのですが、こちらも先ほどのJavaのソースコードと同じく、デフォルトエンコードの影響を受けます。

図26 日本語のコメントを含む build.gradle の実行例(エラーになる)
図26

こちらもJavaのソースコードと同様に、

  • build.gradleをプラットフォームのデフォルトエンコードに合わせる
  • build.gradleのエンコードを明示する

の2通りの対策が考えられますが、Javaのソースコードと異なり後者の対応が簡単ではありません。なるべくエンコード設定の範囲を狭めたいと思ったのですが、コマンドライン、Android Studioの両方で有効だったのは環境変数JAVA_OPTSを使う方法でした。

表2 build.gradleのエンコードの指定箇所
エンコードの指定箇所Android Studioコマンドライン
<HOME>/.gradle/gradle.propertiesに設定無効有効
環境変数JAVA_OPTSに設定有効有効
リスト6 エンコードの指定方法
<HOME>/.gradle/gradle.properties
  org.gradle.jvmargs=-Dfile.encoding=UTF-8

環境変数 JAVA_OPTS
  export JAVA_OPTS='-Dfile.encoding=UTF-8'

このいずれの方法もbuild.gradleのエンコード指定」ではなく「デフォルトエンコードを強制的に変更する」という意味にあたります。この設定をしてしまうと、先ほど紹介した「Javaのソースコードのエンコード指定」も軒並み影響を受けるため、個人的には身もフタも無いやり方だと思っています。build.gradleに対するスマートなエンコード指定があって欲しいものです(なおGroovyスクリプトのエンコード指定であるgroovy.source.encodingはGradleには有効ではないようです⁠⁠。

このあたりの詳細についてはJGGUGのuehajさんが自身のブログで説明されています。

この説明で言及のあった3つの解決策のうち、最後の1つがGradleで日本語コメントを使う妥協点なのでは?と思いました。

教訓は、デフォルトエンコーディングとスクリプトのエンコーディングが異なるなら(1)文字コード変換するか(2)実行時に正しくencodingを指定せよ (3)スクリプトのコメントについて文字コードなんてこまけーこたあ良いんだよ、といいたい場合は、/**/を推奨。⁠or行末に空白でも入れとけ)

コメントに何を書いてもいい」と思うのは、/**/については正しいが、//については正しくない - uehaj's blog

つまりは、図27のようなコメントスタイルを用いた方が良いのでは?という話です。

図27 ブロックコメントだと日本語が含まれても平気
図27

「行コメントの後に空白を入れておく」のは、エディタの設定で『不要な空白を除去する』事が可能なため推奨しません。

[TIPS#8]Android Studioに「Gradleの割り当てメモリが足りない」と怒られます

図28 Gradleの割り当てメモリ不足エラー
図28

このエラーはWindowsで32bit JVMを使っている場合に見かけます(Mac版では見かけたことがありません⁠⁠。どうもAndroid Studioが内部で実行しているGradleに割り当てているメモリが 1024MB(-Xmx1024m)であることが起因しているようです<AS_SYSTEM>/log/idea.logで確認できます⁠⁠。

これを回避するために<HOME>/.gradle/gradle.propertiesリスト7のような設定を追加します。

リスト7 gradle.propertiesに割り当てメモリの指定をする
org.gradle.jvmargs=-Xmx512m

 The Build Environment - Gradle User Guideより

[TIPS#9]インクリメンタルビルドは無いの?

無いです。

そもそもインクリメンタルビルドはEclipse固有の特徴で、これがあるからEclipseを使っているという人もいるほどです。多少、情報に詳しい人は「IntelliJもver12から自動ビルドが付いたでしょ?」と思われるかもしれません。

Android Studioのビルドが「Gradleベースになった」という罠がここにもありまして、たしかにAndroid Studioにも「Preferences / Compiler」「Make project automatically」という項目がありますが、これを有効にしても自動ビルド(インクリメンタルビルド)は有効になりません。

図29 ⁠Preferences / Compiler」の設定画面
図29

なにより、この「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.gradlegradle.propertiesの完全なリストを載せておきます。

リスト8 <PROJECT_HOME>/MyFirstApp/build.gradle
buildscript {
    repositories {
        maven { url 'http://repo1.maven.org/maven2' }
    }
    dependencies {
        classpath 'com.android.tools.build:gradle:0.4'
    }
}
apply plugin: 'android'

repositories {
    /* Mavenリポジトリの指定 */
    mavenCentral()
}

dependencies {
    compile files('libs/android-support-v4.jar')
    compile 'com.google.code.gson:gson:2.2.4'
    /* ちまちま面倒な場合は、上の2行を消して次の行を有効にする */
    //compile fileTree(dir: 'libs', include: '*.jar')
}

android {
    compileSdkVersion 17
    buildToolsVersion "17.0.0"

    defaultConfig {
        minSdkVersion 7
        targetSdkVersion 16
    }
}

tasks.withType(Compile) {
    /* コンパイル系のタスクでエンコードをUTF-8に指定する*/
    options.encoding = 'UTF-8'
}
リスト9 <HOME>/.gradle/gradle.properties
systemProp.http.proxyHost=proxy.example.com
systemProp.http.proxyPort=8080
#org.gradle.jvmargs=-Xmx512m -Dfile.encoding=UTF-8
org.gradle.jvmargs=-Xmx512m

おすすめ記事

記事・ニュース一覧