Android Studioでライブラリプロジェクトを作る方法

#Android Studioでライブラリプロジェクトを作る方法　の備忘録。
(試した環境：Android Studio 2.1.3)

というよりも、(独立したプロジェクトの)アプリケーションプロジェクトをライブラリプロジェクトに変更する方法ですが・・

本体のプロジェクト
　/appモジュール
　/ライブラリモジュール
ではなくて、

本体のプロジェクト
　/appモジュール
ライブラリプロジェクト
　/ライブラリモジュール
という構成の場合。

1.アプリケーションプロジェクトを作る
File/ New/ New Project...

2.ライブラリ用プロジェクトのappモジュールのApplication Idを空欄にする
appを右クリック/ Open Module Settings
Project Structure画面が開いたら、Flavors/ Application Id を空欄にする。

※この操作をしておかないと、build.gradleの編集を反映した時にエラーが表示される。
"Error: Library project cannot set applicationId."
訳：ライブラリプロジェクトでは、applicationIdは設定できません。

注：(ここではappのままにしてありますが、)モジュール名をapp以外に変更しておいた方が、使いやすいです。例：my-lib-module

3.ライブラリ用プロジェクトのappモジュールの、build.gradleの、apply pluginを変更する
Gradle Scripts/ build.gradle(Module: app) を開く。

apply plugin: 'com.android.application'　を
apply plugin: 'com.android.library'
に変更する。

※2.でApplication Idを空欄にし忘れた場合は、ここで編集しても可。
(defaultConfigの、applicationIdの行を消す)

4.変更を反映する
Gradle files have changed... A project sync may be necessary...	"Sync Now"
と表示される(一部省略)ので、Sync Nowをクリック。

5.必要に応じて、debug/release設定の切替をする
Build/ Select Build Variants

5.ビルドする
Build/ BuildAPK
※MakeProjectだと出力されない

出力先：
app/build/outputs/aar/app-release.aar
など。(BuildAPKを実行した時に、"Show in Explorer"でフォルダを開ける)
aarって何者？という方は、7-Zipとか適当なアーカイバで解凍してみるのがよいかと。


参考：
https://developer.android.com/studio/projects/android-library.html#CreateLibrary
"Convert an app module to a library module"　のあたり。(行程3)

http://stackoverflow.com/questions/27374933/android-studio-1-0-and-error-library-projects-cannot-set-applicationid
ライブラリプロジェクトでは、applicationIdは設定できないので、設定を外しましょう　という内容。(行程2)

http://tools.android.com/tech-docs/new-build-system/applicationid-vs-packagename
applicationIdを設定しないとどうなるの？　その他。
(パッケージ名が使われる。)

##追記1：モジュール名は(デフォルトのappから)変えておいた方がよさげ。
(変えておかないと、インポートした時に、どのライブラリだか分からなくなるので。)
appを右クリック/ Refactor/ Rename...

##追記2：別プロジェクトからライブラリを読み込む方法
####補足：ライブラリを使う側は、この設定だけで使えます。(使う側のプロジェクトでライブラリプロジェクトインポートするとか、モジュールを作るなどの操作は不要です。)

(Android Studio的には、一旦リポジトリに取り込んで、そこから取り出す・・などが推奨だとは思いますが、1行直すたびに登録していられないので。)

本体(ライブラリを使う)側の settings.gradleに追記する(include ':app'　は残したままで)
include ':my-lib-module'
project(':my-lib-module').projectDir = new File(settingsDir, '../MyLibProj/my-lib-module')
※モジュール名、パス等は適当に読み替えて下さい。
※参考ではモジュール名が2階層になっていますが、1階層にしておいた方が無難かと。

本体(ライブラリを使う)側の build.gradleのdependencies{}の中に追記する
compile project(':my-lib-module')
※Project StructureのappのDependenciesの設定です。
※本体側のビルドで、ライブラリモジュールのビルドも呼ばれます。

何をしているかというと・・
・使用するモジュールに、ライブラリモジュールを追加する
・使う側のプロジェクトから見える、ライブラリモジュールのパスを、付け替える
　(モジュールがある場所を指定しているだけで、ファイル移動やコピーではありません。)

正しく設定できていれば、Projectビューに、ライブラリモジュールが表示されるはずです。

参考(追記2)：
ライブラリ(モジュール)のprojectDirだけ付け替える方法
http://stackoverflow.com/questions/9744721/relative-project-dependencies-in-gradle

[Configure Build Variants - Declare Dependencies]
https://developer.android.com/studio/build/build-variants.html#dependencies

###追記2-1　(追記2の追記)：
ライブラリプロジェクトでビルド(BuildAPK)した後に、(読み込み側にコピー用タスクを作っておいて) 出力をコピーしても良さそうですが、ビルドの手間が増えるので見送り。(ライブラリをビルド、読み込み側でコピー(またはモジュールのインポート)、ビルド)

参考(追記2-1)：
http://stackoverflow.com/questions/30636905/gradle-copy-file-after-its-generation
ファイルをコピーする場合の資料

https://developer.android.com/studio/projects/android-library.html#AddDependency
モジュールをインポートする場合の資料

## 追記3　ライブラリモジュールのbuild.gradle
ライブラリの使用(配布)方法に応じて、2パターンに分かれると思います。
3-1：ライブラリをアプリに組み込む場合
3-2：ライブラリ単体で配布する場合
Build Typesとproguardの設定ファイルを、パターンに応じて個々に作成しておくとよいと思います。(proguardのkeep設定などが異なるので。)
以下、ファイル名などは適宜読み替えて下さい。

### 追記3-1　ライブラリモジュール自体を、アプリ本体のプロジェクトにインポートする場合の設定
ライブラリプロジェクトも手元にあって、ライブラリモジュール自体を、アプリ本体のプロジェクトにインポートする場合は、アプリ本体側のbuild.gradleに設定を集約するべきかと思います。

#### 3-1-1　Proguardの設定(proguard-rules.proなど)
##### アプリ本体(Module: app)用のproguardの設定ファイルに、設定を集約します。
(-keep class com.android.vending.billing.**など)

##### ライブラリ(Module: ライブラリモジュール名)用のproguardの設定ファイルは、特に設定しません。
難読化により、アプリ本体で使用するクラス、メンバ名は変更されるetc　ので、ライブラリ側の設定ファイルでのkeep設定は不要。詳細は、出力されたmapping.txtなどを参照。

#### 3-1-2　build.gradleの内容
##### アプリ本体(Module: app)用のbuild.gradle
```
例：
release {
    minifyEnabled true
    proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
    proguardFile '(ライブラリモジュールのパス)/proguard-rules.pro'
}
```
などを設定します。
※minifyEnabled、proguardFileの設定は、Android Studioの設定画面から入力可。
##### ライブラリモジュール用のbuild.gradle
```
例：
release {
    // minifyEnabled false
    // proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
}
```
処理はアプリ本体側に任せるので、設定は空でよいと思います。
※Build Typesをrelease、debug以外にした場合は、自動的にreleaseなどが作られる事があるので注意。

### 追記3-2　ライブラリ単体(aarファイルなど)での配布をする場合の設定

#### 3-2-1　Proguardの設定
※必要に応じて、アプリ本体に組み込んで使う用(proguard-rules.proなど)のファイルとは別のファイルにしておきます。
(例：proguard-rules-as-a-library.proなど)

※aarファイル単体で配布する場合、Proguardを使う場合は、minify(不要なものを削除)への対策・名前の変更への対策が通常は必要かと思います。(keep～など)
ようするに、「Proguardを使わない」か、「Proguardを使う、かつ、consumerProguardFilesを書く」の2択になると思います。

#### 3-2-2　build.gradleの内容
##### ライブラリモジュール用のbuild.gradle
Proguardの設定ファイルを、アプリ本体用のモジュールに組み込んで使うためのProguardの設定ファイル(3-1-1)と別ファイルにした場合は、Build Typesも分ける必要があります。

release設定と共通の設定でよい場合は、Build Typesを分ける必要なし。
(安全のため、分けておくのも1手。)
```
例1：(Build Typesを、release_as_a_libraryとし、minifyを使わない場合)
buildTypes {
    release_as_a_library {
        // minifyEnabled false
        // consumerProguardFiles 'proguard-rules-as-a-library.pro'
    }
}
```

ライブラリモジュールで、aarファイルにProguardの設定を含めたい場合は、
ライブラリモジュールのbuild.gradleで、
consumerProguardFiles
を使います。
```
例2：(Build Typesを、release_as_a_libraryとし、minifyを使う場合)
buildTypes {
    release_as_a_library {
        minifyEnabled true
        consumerProguardFiles 'proguard-rules-as-a-library.pro'
    }
}
```
※この例2では、(あえて)minifyEnabledをtrueにしていますが、
ライブラリの特性を考えると、通常は、minifyEnabledをfalseに設定(または指定せず)、ライブラリにProguardの設定を含めない(minifyしないならkeepも不要)かと思います。
(通常、ライブラリは、クラス、メンバ名を公開し、かつ、ライブラリを使う側が、どのクラス、メンバを使うか決めるので。)

参考：
[Stackoverflow - Proguard ignores config file of library]
http://stackoverflow.com/questions/26983248/proguard-ignores-config-file-of-library

[Android Studio Project Site - New Build System]
0.5.7
http://tools.android.com/tech-docs/new-build-system
> Proguard support for libraries. Note the current DSL property 'proguardFiles' for library now sets the proguard rule file used when proguarding the library code. The new property 'consumerProguardFiles' is used to package a rule file inside an aar.

このリリースノートを読むと、consumerProguardFilesの他にproguardFilesも書く必要があるように思えるので、要検証。(proguardFilesは書かなくても動作するようですが)

---
ここから旧記事の名残
##### minifyEnabledの設定に注意する
ライブラリモジュールのbuild.gradleで、
minifyEnabled true
の設定があると、ビルドが通らないのは、
ライブラリ内でライブラリ内のクラス/クラスメンバを使っていないので、
(keepオプションを付けていないものが) 削られてしまうため。
ライブラリでは、読み込み側がライブラリ内のクラスやクラスメンバを使うか使わないかの判定ができないので、minifyEnabledをtureにする意味があるのか、という問題はありますが・・・

minifyEnabledを設定しない(あるいはfalseにする)、
または、
proguard-rules.proにkeep～などの設定を書く必要がある。
※keep～の設定を書いた場合は、ライブラリモジュールを使う側で、ライブラリモジュールのproguard-rules.proを読み込むのを忘れないようにする。

Messageウインドウ(またはGradle Console)に表示されるエラーの例
> Warning:Exception while processing task java.io.IOException: The output jar is empty. Did you specify the proper '-keep' options?
> :(ライブラリモジュール名):transformClassesAndResourcesWithProguardForRelease FAILED
> Error:Execution failed for task ':(ライブラリモジュール名):transformClassesAndResourcesWithProguardForRelease'.
> \> java.io.IOException: The output jar is empty. Did you specify the proper '-keep' options?