AndroidのGradleプロジェクトをオフラインでビルドする

Androidアプリを完全にオフラインでビルドする必要が生じたためやってみました。
gradleの場合、ant + ivyなんかと違ってプラグインが足引っ張ってオフライン化が面倒なのでサンプルとメモを残しておきます。

※ちなみに、検索するとAndroidStudioでoffline workにチェックを云々とか出てきますが、それやっても他人のマシンに持っていくとビルド通りません。

# サンプルプロジェクト
説明が長ったらしいのでサンプルを先に置いておきます。
依存ライブラリは最低限のみを同梱しているため、通常はこれをベースにすれば問題ないと思います。

[https://github.com/hhashimoto/gradle-android-offline-build](https://github.com/hhashimoto/gradle-android-offline-build)

# オフラインビルドめも
以下、必要に応じてご参照ください。

## Android Gradle Pluginのビルド

[http://tools.android.com/build/gradleplugin](http://tools.android.com/build/gradleplugin)を参考にプラグインをビルドします。

### ビルド環境

- OS  : Ubuntu14.04 64bit
- HDD : 20GB以上
- ソフトウェア : OpenJDK6

----

### 事前準備
ビルドに必要なライブラリと、ソースをダウンロードしてくるためにrepoコマンドをインストールします。
repoは好きな場所にインストールしてください。

```
$ sudo apt-get install bison g++-multilib git gperf libxml2-utils
$ mkdir bin
$ curl https://storage.googleapis.com/git-repo-downloads/repo > ~/bin/repo
$ chmod a+x ~/bin/repo
$ echo "export PATH=$PATH:~/bin" >> ~/.bash_profile
$ source ~/.bash_profile
```

なお、ライブラリはOSのバージョンによって変わってくるため、必要に応じて[http://source.android.com/source/initializing.html](http://source.android.com/source/initializing.html)を参照してください。

上記URLに記載されていないOSでは少なからずつまづくことがあると思いますので、Ubuntuにしておくのが無難です。

----

### ソースのチェックアウト

[http://tools.android.com/build](http://tools.android.com/build)にプラグインのソースをチェックアウトするコマンドが記載されているのでコピペします。
repoはカレントディレクトリにメタデータを置くので、適当にディレクトリを切ってからチェックアウトします。
8GBくらいだったか、結構容量を食うのと、初回のsyncにはかなり時間がかかるので注意。

```
$ mkdir gradle_1.0.0
$ cd gradle_1.0.0
gradle_1.0.0 $ repo init -u https://android.googlesource.com/platform/manifest -b gradle_1.0.0
...
repo has been initialized in /home/vagrant/gradle_1.0.0
gradle_1.0.0 $ repo sync
...
Syncing work tree: 100% (30/30), done.
```

----

### ビルド

[http://tools.android.com/build/gradleplugin](http://tools.android.com/build/gradleplugin)からコピペします。

```
gradle_1.0.0 $ cd tools
gradle_1.0.0/tools $ ./gradlew init
...
:buildSrc:build

FAILURE: Build failed with an exception.

* Where:
Build file '/home/vagrant/gradle_1.0.0/tools/base/build-system/integration-test/build.gradle' line: 19

* What went wrong:
A problem occurred evaluating project ':base:integration-test'.
> Cannot set maxParallelForks to a value less than 1.

* Try:
Run with --stacktrace option to get the stack trace. Run with --info or --debug option to get more log output.

BUILD FAILED
```

エラーが出たので当該のbuild.gradleを編集します。

これはVirtualBox上の仮想環境でビルドを行った影響かもしれません。
とりあえず2並列くらいなら問題ないと思うので、2に設定しました。

```
gradle_1.0.0/tools $ vim base/build-system/integration-test/build.gradle
-    maxParallelForks = Runtime.runtime.availableProcessors() / 2
+    maxParallelForks = 2
```

再度initします。ゴミを消すため、cleanを併せて行うようにします。
initが通ったらassembleします。単にassembleするとビルドに失敗するのでcleanを挟みます。

```
gradle_1.0.0/tools $ ./gradlew clean init
...
BUILD SUCCESSFUL

gradle_1.0.0/tools $ ./gradlew clean assemble
...
BUILD SUCCESSFUL
```

----

## Mavenリポジトリの作成

アプリのビルド時にプラグインの依存関係が解決できないといけないので、maven形式のリポジトリを作成します。
例によってコピペです。

```
gradle_1.0.0/tools $ ./gradlew publishLocal
...
Uploading: com/android/tools/uiautomatorviewer/24.0.0/uiautomatorviewer-24.0.0.jar to repository remote at file:/home/vagrant/gradle_1.0.0/out/repo
Transferring 66K from remote
Uploaded 66K
:publishLocal

BUILD SUCCESSFUL
```

成功すると、out/repoにリポジトリが作成されるので、アプリのプロジェクトから参照できるところにコピーします。

```
gradle_1.0.0/tools $ cp -r ../out/repo /path/to/app_project
```

続いて、gradle pluginの依存するライブラリがprebuilts以下のmavenリポジトリに入っているのでコピーします。
必要最小限をコピーするかすべてコピーするか、依存ライブラリをコピーするタスクを書くかといった選択肢がありますが、今回は面倒なのですべてコピーします。(サンプルプロジェクトでは最低限のみリポジトリに含めています)

```
gradle_1.0.0/tools $ cp -r ../prebuilts/tools/common/m2/repository/* /path/to/app_project/repo
```

----

## アプリのオフラインビルド

アプリプロジェクトのbuild.gradleを編集し、プラグインのリポジトリを参照できるようにします。
build.gradleを編集したら、--offlineオプションをつけてビルドします。

```
$ cd /path/to/app_project
app_project $ vim build.gradle
buildscript {
  repositories {
-    jcenter()
+    maven { url 'repo' }
  }
  dependencies {
    classpath 'com.android.tools.build:gradle:1.0.0'
  }
}
...
app_project $ ./gradlew --offline clean build
...
BUILD SUCCESSFUL
```