はじめに
今回はAndroid Studioのプロジェクト設定についての話です。このあたりは不安定で、安定するまで触れないほうがいいかなと思いましたが、それだと致命的なほどできないことだらけになるので、避けては通れない道だと踏ん切りました。
Android Studioのプロジェクト構成とビルドツールGradleは切っても切れない間柄にあるのですが、一度にすべてを説明するのは難しいので、前後編に分けて説明します。前編にあたる今回は、以下のような基礎的な話を中心に説明を行います。
- プロジェクトの設定にどのような種類があるのか
- それらの設定情報がどう管理されているか
後編では、Gradleのビルドスクリプトを絡めたプロジェクトの設定変更やTIPSなど実用的な話をする予定です。
今回はウンチク中心になりますので、全部読むのが億劫な方は次の3点だけ覚えて貰えれば、今回の目的は達成します。
Android Studioのプロジェクト設定はちょっとしたまやかしで、ここを変更してもビルドに影響は与えません
- ビルドは、Android Studioではなく、Gradleが行っているためです
- それでもAndroid Studioにプロジェクト設定をしておかないと、エディタのコード補完が正しく行えません
プロジェクトの設定を変更したければ、Gradleのビルドスクリプトbuild.gradle
を修正しなければなりません
- ビルドに関する情報を握っているのは
build.gradle
です
- Android Studioのプロジェクト設定は、
build.gradle
からの投影でしかありません
プロジェクト設定や設定変更に関してはAndroid StudioよりGradle、特にAndroid用プラグインが重要になります
【注意】:Android Studioは開発バージョンであるため、今回紹介した問題はいずれ解決される可能性があります(今回はv0.1.2で試しました)。
プロジェクトの基礎知識
まずAndroid Studioがどのようにプロジェクトを管理しているのが知っておきましょう。プロジェクト管理を知る上で必要となる概念は、ProjectとModuleです。
Android開発に興味のある方の多くはEclipseをよくご存じかと思いますので、Eclipseと比較してみます(表1)。
表1 EclipseとAndroid Studioの構成情報の対応(FAQ for Eclipse Usersより)
Eclipse | Android Studio |
Workspace | Project |
Project | Module |
Project-specific JRE | Module JDK |
User library | Global library |
Classpath variable | Path variable |
Project dependency | Module dependency |
Library | Module library |
広い意味で取れば、Android StudioのProjectはEclipseのワークスペース(Workspace)に相当しますが、Eclipseと異なり関連のあるModuleだけで構成されています。そのため感覚的には
「EclipseのProject=Android StudioのProject+Module」
のほうがしっくり来るのではないでしょうか。
仕方が無いことなのですが、このようにIDEによってプロジェクト管理方法や用語が異なることが、Android Studioへの乗り換えやEclipseとの併用の大きな妨げになっていると思います。
Android StudioのベースとなったIntelliJでは、プロジェクトを作成すると「Projectと同じ場所に1つのModuleができる」が基本形なのですが、Android StudioではGradleとの兼ね合いにより、
「Projectと同じ場所にModuleが1つ、さらにその下にもう1つのModuleができる」
を基本形にしています(理由は追って説明します)。
プロジェクトの設定手段
Project、Module といった管理対象が、どこで設定されているかを説明ます。Android StudioがProjectやModuleに対して行える設定手段は次の3種類あります。
Project Structure
Moduleの依存関係、ProjectやModuleのパス設定、SDKやライブラリの指定など主にファイルパスまわりの設定を行います。
設定画面の開き方は、メニューバーの「File→Project Structure」か、ツールバーの「Project Structure」から行います(図1)
Project Settings
コードフォーマットのスタイル指定、ファイルのエンコード指定、バージョン管理の設定などプロジェクト固有の各種設定を行います。身もフタも無い言い方ですが、Project Structureで設定できないものはすべてこちらで設定します。
設定画面の開き方は「アプリケーションメニュー→Preferences...」(WindowsやLinuxはメニューバーの「File→Settings」)か、ツールバーの「Preferences(Settings)」ボタンから行います(図2)。
「Preferences」画面は、Android Studioの設定画面も兼ねており、Project固有の設定は「 Project Settings [ ProjectName ] 」が相当します(図3)。
Run/Debug Configuration
エミュレータで実行する/テストを実行する、といったプロジェクトの実行構成を定義します。
設定画面の開き方は、メニューバーの「Run→Edit Configurations」か、ツールバーの「Run/Debug Configuration→Edit Configurations」から行います(図4)。
「Run/Debug Configuration」はさておき、プロジェクト設定が「Project Structure」と「Project Settings」に分かれていることに違和感を感じた方も多いと思います。EclipseやNetBeansでは「プロジェクトプロパティ」として1つに括っているものが、Android Studioでは2つに分かれています。
「これには何か深い意味でもあるのだろうか?」と深読みするかも知れませんが、何のことはありません。「昔からこうだった」だけです。Android Studioはできたてホヤホヤどころか開発真っ最中の新しいIDEですが、ベースにしているIntelliJは10年以上の古い歴史を持つIDEです。10年前は設定項目も少なかったため、当時は良かれと思って分類した「Project Structure」と「Project Settings」ですが、バージョンを重ねるにつれ設定項目が増えていき、今のような状態になりました。
そんな事情も知らない新しいユーザには単なる混乱の元でしかありませんね。
話を元に戻します。プロジェクトに対する3種類の設定「Project Structure」「Project Settings」「Run Configurations」ですが、その実体は.ideaディレクトリと.imlファイルに格納されます(図5)。
.ideaディレクトリのどのファイルが何の情報を持つかについて、すべては説明しませんが、これらの管理ディレクトリ(とファイル)について簡単に説明しておきます。
.ideaディレクトリ
「Project Structure」や「Project Settings」のほとんどがこのディレクトリ内に格納されています。Android Studioのプロジェクトディレクトリの証でもあり「.idea」があるディレクトリをプロジェクトとして認識します(Android Studioなのに名前が「.idea」なのはご愛敬)。
余談ですが、Android Studio以外にも、IntelliJやそれをベースにしている他のIDEもプロジェクトディレクトリに「.idea」を使っているので、IntelliJなどを共用しているとちょっと困った事になります(どのIDEも「それは自分のプロジェクトだ」と認識するので)。
*.imlファイル
Moduleに関する情報(正確には「Project Structure」の一部と「Run/Debug Configurations」)が保存されています。名前から察するに「 IntelliJ ModuLe」の略だと思います。
この2つがEclipseでいう .projectと .classpathに相当します。
Project Structureで管理している情報
プロジェクト構造を管理している「Project Structure」について説明します。「Project Settings」や「Run/Debug Configurations」はプロジェクト構造にそれほど関わりが無いので割愛します。
「Project Structure」画面は、Android Studio v0.1.1では開けなくなりましたが、v0.1.2からは図7のような警告が出たのち開けるようになりました。
要約すると「Project StructreのちゃんとしたUIはあとで提供するから、しばらくbuild.gradle
を直接編集しておいて。あと、ここで設定した内容はbuild.gradle
に反映されないから」と言ったところです。
「Project Structure」画面の左側にリストアップされているのが設定項目です。一番上の「Project」から「Artifacts」までは Project固有 の設定ですが、下側の「SDKs」と「Global Libraries」はAndroid Studio全体の設定です。
それぞれの項目の意味は以下の通りです。
Project(プロジェクト)
Project共通の設定としてSDKやビルドパスなどを指定します。
Modules(モジュール)
Projectを構成するModuleそれぞれの設定を行います。Moduleの設定では、ソースパス、ビルドパス、参照するライブラリやモジュールを指定します。ここが、Project Structureの本命部分と言えます。
Android Studioではソースパスをプロダクトコード用とテストコード用に分けて管理することができます。Moduleやソースパスは、Projectツールウィンドウでは表2に示すアイコンで表現されます。
表2 Projectツールウィンドウのアイコン例
アイコン | 意味 |
| Module |
| プロダクトコード用ソースディレクトリ |
| テストコード用ソースディレクトリ |
パスについては、このほかに「Excluded Folders(除外ディレクトリ)」という概念があり、これに指定されたディレクトリは、Android Studioからは「無いモノ」として扱われます。
Android StudioのProjectとModuleには上下関係があり、Projectの配下に1つまたは複数のModuleで構成されます。Module同士に依存関係はありますが、Moduleの下にModuleを作ることはできません。
Libraries(ライブラリ)
Projectで共有するライブラリを定義します。ここで定義されたライブラリはProjectに属しているModuleが参照できます。これ以外に、特定のModule内で定義したライブラリとAndroid Studio全体で共有できるライブラリ(Global Libraries)があります。
Facets(ファセット)
Java以外の開発言語や特定のフレームワークなどをサポートしているかどうかを定義します。FacetはModuleに紐付けられます。たとえば「foo ModuleがAndroidをサポートしている」ならば「foo Module」に「Android Facet」が紐付きます。
このFacetはAndroid Studio(やベースとなったIntelliJ)固有の概念で、設定できるFacetはプラグインによって増減します。Android Studioの登場により「ScalaやKotlinでAndroid開発ができるのでは!?」と期待に胸が膨らんだ人もいると思いますが、もうしばらく様子をみたほうが良さそうです。
Artifacts(アーティファクト)
Projectの成果物を定義します。成果物とは、JarファイルやApkファイルのことです。
SDKs, Global Libraries
これらはプロジェクト固有の設定ではなくAndroid Studio全体の設定です。「SDKs」は第4回で紹介したとおり、JDKやAndroid SDKといったSDK全般を管理しています。「Global Libraries」はAndroid Studioに事前定義した外部ライブラリを管理しています。「SDKs」はさておき「Global Libraries」を使うことはほとんど無いでしょう。
ここまでがAndroid Studioのプロジェクトに関する基礎知識です。この知識を元にAndroid Studioが作成したプロジェクトの中身を紐解いていきます。特に、Project Structureの Project, Modules, Libraries がどうなっているか注目してください。
Androidプロジェクトひとめぐり
すでにネタバレしてますが、Android Studioが作成したプロジェクトはGradleのビルドスクリプトを中心に管理されており、プロジェクトの構造やビルド手順などのほとんどがGradleに依存しています。
GradleとはGroovyベースのビルドツールでMavenとAntの良いとこ取りをしています。ビルドスクリプトであるbuild.gradle
はMavenのPOMのように「プロジェクト構造」を表しつつ、Antのように自由にタスクを追加することができます。
GoogleのAndroidチームの一員であるAlex Ruizがご自身のブログで興味深いことを述べていたので、それを引用します(引用元は、株式会社サムライズムによる翻訳版です。強調は筆者が行いました)。
我々のゴールはGradleセントリックにすること
我々は新しいGradleベースのビルドシステムを開発するため、Gradlewareの方々と密に働います。今現在Android Studioでは新しいGradleベースのAndroidプロジェクトを作るか、既存のプロジェクトをインポートするかを選択できます。Android Studio上でビルドをする際、IDEAのデフォルトのJava builderは無効化して処理はGradleに委譲しています。Android Studioによるものも、コマンドラインによるものも、ビルド成果物は全く同じです。 我々のゴールはGradleのビルドファイルを唯一の真実の源とすることです。
【翻訳】Android Studio: Googleの新しく、輝かしいAndroid IDEより
この「Android Studio上でビルドをする際、IDEAのデフォルトのJava builderは無効化して処理はGradleに委譲しています。 」が非常にくせ者でして、この仕組みのお陰(?)でAndroid Studioでは「Project Structre」より、Gradleのビルドスクリプトbuild.gradle
がとても重要になります。
では第3回で作成したプロジェクトを見ながら、GradleとAndroid Studioがどう関係しているか覗いてみましょう。図9は第3回のプロジェクトをAndroid Studio v0.1.2で作り直したものです。
v0.1.2からプロジェクトのディレクトリ名とモジュールのディレクトリ名が表3のように変わりました。プロジェクト名とモジュール名が同じなのは何かと混乱の元だったので、このほうが良いと思います。
表3 v0.1.1以前とv0.1.2のプロジェクト名、モジュール名の違い
| v0.1.1以前 | v0.1.2 |
プロジェクト名 | MyFirstApp | MyFirstAppProject |
モジュール名 | MyFirstApp | MyFirstApp |
※ プロジェクト名に「MyFirstApp」を指定した場合
プロジェクトのトップディレクトリ(<PROJECT_HOME>
)の真下と、<PROJECT_HOME>/MyFirstApp
にGradleのビルドスクリプトであるbuild.gradle
があります。これはGradleのマルチプロジェクトを表しています。
<PROJECT_HOME>/build.gradle
の中身は空で、サブプロジェクトに何を含めるかは <PROJECT_HOME>/settings.gradle
に定義してあります。
プログラム本体を含んでいるサブプロジェクト:MyFirstApp側のビルドスクリプトはリスト2の通りです。
build.gradle
の詳細な説明は省きますが、Android Studioが作成したビルドスクリプトはAndroid Tools Project Siteで公開しているGradle Pluginを利用しています。
Project Structureとbuild.gradle
Project Structureの設定を見ながら、build.gradle
がどう反映されているか確認してみましょう。
Projectの設定内容
まずは「Project」設定です(図10)。
ここではProject SDK(Projectが使うSDK)、Project language level(言語レベル)、Project compiler output(出力ディレクトリ)を定義しています。
Project SDKには、Android SDKが設定されますが「複数のAndroid SDKが登録されている場合、どれが設定されるのか?」という傾向はわかりませんでした。面倒を避けるのであれば、Android Studioに複数のAndroid SDKを定義しないほうが身のためなのかもしれません(どのみちGradleが利用するのは<PROJECT_HOME>/local.properties
に設定してあるAndroid SDKです)。
Android Studioに設定しているAndroid SDKのJava SDKが1.6でも1.7でも、プロジェクト作成時に作られる<PROJECT_HOME>/MyFirstApp/build.gradle
のバージョン指定部分に変化は起きませんでした(常に「1.7」でした)。
また「Project language level(言語レベル)」は「6.0 - @Override in interfaces」が設定されており、build.gradle
のtargetSdkVersionと連係しているように見えますが、おそらく単なる決め打ちなのだと思います。
「Project compiler output(出力ディレクトリ)」については設定しているだけで、この値が使われることはありませんし、そのディレクトリ<PROJECT_HOME>/build
も存在しません。
Modulesの設定内容
続いてModulesです。Moduleは2つ定義してあります。1つは<PROJECT_HOME>/build.gradle
に相当するMyFirstAppProjectと、もう1つが<PROJECT_HOME>/MyFirstApp/build.gradle
に相当するMyFirstAppです(Android v0.1の時と名称が異なる点に注意してください)。
それぞれのModuleが、Gradleのビルドスクリプトに対応しています(リスト3)。
Android Studioは、GradleのビルドスクリプトをModuleとしてしか認識できないため、意味的にAndroid StudioのProjectに相当する<PROJECT_HOME>/build.gradle
もModule(MyFirstAppProject)として認識します。よって、結果的には2つのビルドスクリプトに対応する2つのModuleができるわけです。
それぞれのModuleにFacetが設定されているのが確認できると思います。どちらのModuleにも Android-Gradle Facetが設定されており、いずれも「Gradleプロジェクト」であることを示しています。さらに MyFirstApp Moduleには Android Facetが設定されいて、このModuleがAndroidプロジェクト本体であることを示しています(今のところFacetそのものに設定項目は無いようです)。
ちなみに、この画面から新しいModuleやFacetの追加ができるのですが、Gradleと連係しないため、いたずらにプロジェクト構成を混乱させる結果になるだけなので使用しないでください。
では、それぞれのModuleの定義内容を見てみましょう。
まずMyFirstAppProject Moduleですが、こちらはプログラムが存在しないので、設定らしい設定がほとんどありません。MyFirstApp Moduleとの依存関係を握っているはずですが「Dependencies」タブに特筆する内容はありませんでした。
強いて言えば「Sources」タブで、Gradleの管理ディレクトリ: <PROJECT_HOME>/.gradle
と先ほどの「Project compiler output」の<PROJECT_HOME>/build
が「Excluded Folder」に指定されている程度です。
続いて、MyFirstAppModuleです。こちらはプロジェクトの本体でもあるため、設定されている値も豊富です。「Sources」タブを見てみると、実際に作成されているディレクトリより数多くのディレクトリが「Source Folders」や「Test Source Folders」に定義されている事がわかります(赤字は存在してないディレクトリを意味します)。
これらがbuild.gradle
の情報を読み取って定義したものなのか、単なる決め打ちなのかはわかりません。今後の機能追加に備えて、いろいろ準備しているのかなと推測できます。
当然ですが、ここで定義済みで存在していないディレクトリを実際に作成すると、即座に認識されます(ただし、テスト用ディレクトリが事前定義されているからと言ってテストコードが動くわけではなさそうです)。
「Paths」タブは、MyFirstAppProject Module同様、特筆するような内容は定義されていませんでした。
最後に「Dependencies」タブです。ここにはMyFirstApp Muduleが参照するライブラリとしてandroid-support-v4がCompileスコープとして定義されています。
このライブラリandroid-support-v4は「Libraries」に Project Library として定義されています(ライブラリの実体は<PROJECT_HOME>/MyFirstApp/libs
にあります)。
この設定は<PROJECT_HOME>/MyFirstApp/build.gradle
のdependencies
と連動しているように見えます。
思わず、他の関連ライブラリを追加してみたくなりますが、まだ待っててください。詳細は次回説明しますが、なんの準備もなく「Dependencies」タブにライブラリ設定を行ってもビルドには反映されません。
Librariesの設定内容
先ほど紹介したとおり、Project共通のライブラリが定義されています。
Facetsの設定内容
Moduleに設定されているFacetsを、Facets側から見た内容が表示されます。
Facetsの追加は、この画面か先ほどのModulesから行う事ができますが、Module追加と同様に期待した結果にはならないので、しばらく使わないほうがよいでしょう。ライブラリと同様に、Facetsを追加しただけではビルドに影響を与えません。
デフォルトで用意されているGroovy Facetは「Android StudioでGroovy開発ができる」というより、Gradle連携をするために同梱しているGroovyプラグインのため「たまたま選択可能になっている」ととらえた方がよさそうです。
Artifactsの設定内容
本来は、ここでProjectの成果物(Artifacts)を設定するのですが、何も設定されていません。
ビルドはGradleが行うため、成果物の作成もGradleが行っています。実のところ、プロジェクトを新規作成した直後に自動でビルドが行われており、その時点で成果物も作られています(<PROJECT_HOME>/MyFirstApp/build/apk
に生成されている)。
仮にArtifactsに何かしらの成果物(JarやApk)を設定してビルド(メニューバーの「Build→Build Artifacts...」)をしても、何も生成されません。
前編のまとめ
Android Studioのプロジェクト設定のうち、Project Structureを重点的に説明してきました。しかし、ビルドがGradleベースであるため、Project Structureの設定を変更してもビルドになんら影響を与えません。ライブラリを追加したり、成果物を指定したりするのは、すべて build.gradle
に定義しなければなりません。
「ここまで読んだのにムダだったの?」と落胆するかと思いますが、それでもProject Structureには意味があってbuild.gradle
に定義した内容をProject Structure側にも反映しないと、Android Studio上での開発に支障をきたします。
端的な例で言えば、build.gradle
に関連ライブラリを定義しても、「Project Structure / Modules / Dependencies」にそのライブラリを定義しなければ、Android Studioのエディタ上に、そのライブラリは認識されません。つまりコード補完の対象にもならず、ライブラリを利用したコードを記述すると参照エラーとなります。
ビルドをGradleベースにしたとしても現状(Android Studio v0.1.2)ではbuild.gradle
とシームレスに連係しているとは言えない状態であるため、今回紹介したような仕組みを覚えておいて損はありません。
後編では、Gradle側(build.gradle
)に視点をあてて、ライブラリの追加方法のような「こんな時どうするの?」的なTIPSを説明します。