TensorFlowをBazelを使わずAndroid Studioでビルド&実行する

# はじめに
Googleが公開しているTensorFlowを使った[Android Camera Demoアプリ](https://github.com/tensorflow/tensorflow/tree/master/tensorflow/examples/android)を実行するにあたり、ネット上にいくつか解説記事があるものの、どれもBazelを使ってビルド・実行しています。

* <http://qiita.com/tomoima525/items/99a2df5cb0559c41647a>
* <http://qiita.com/tchkwkzk/items/aa481db14126b6abdaa1>

もちろんBazelを使ってもいいのですが、TensorFlow本体のコードまで含むためプロジェクトが肥大したり、そもそもNDKのパス設定やr12bじゃないとビルドできない不具合があったりで不便。Bazelを使わなくても、TensorFlow関連のライブラリはjcenterやJenkinsから取得可能。

この記事は、次のような方を対象に、**Bazelを使わずできるだけ簡単にデモアプリを実行する**手順のメモです。

* **できるだけシンプルで簡単にアプリをビルドして実行したい**
* **Bazelを使ってビルドするとTensorFlowのソースまで含むためプロジェクトが膨大して嫌**
* **これまで同様、Android Studioを使ってアプリを管理・開発したい**
* **TensorFlowを使ったアプリの開発はじめるのでテンプレートがほしい**


# 公式デモアプリの準備
TensorFlowの公式リポジトリをClone。
今回はBazelを使わないので、TensorFlowの不要な部分は削除。

```bash
git clone https://github.com/tensorflow/tensorflow.git
mv tensorflow-master/tensorflow/examples/android ./<your project name>
rm -r ./tensorflow-master __init.py__ gradleBuild/ jni/ sample_images/
```

# TensorFlow関連のライブラリをセット

## ダウンロード
公式のREADMEでも少し振られれていますが、ここからすでにビルド済みのライブラリフィアルがダウンロードできます。
<http://ci.tensorflow.org/view/Nightly/job/nightly-android/>

ビルド履歴の最新版 → ビルドの成果物 → out → native → (すべてのファイルをzipで)

## Androidプロジェクトに配置
まず、プロジェクト内にライブラリファイルを格納するディレクトリを作成。
デフォルトでカウのディレクトリ名はlibsに設定されている。(`<project root>/build.gradle: 130行目`)

```bash
cd <your project name>
mkdir libs
```

次に、`libs`ディレクトリ下にアプリを実行する端末のCPU ABI名のディレクトリを作成。基本的には`armeabi-v7a`になると思います。

```bash
cd libs
mkdir <CPU ABI name>
```

# 

最後に、先程ダウンロードしたzipファイルを解凍して、CPU ABI名のディレクトリ配下にある以下4つのファイルを`libs/<CPU ABI name>/`ディレクトリに格納。

* `benchmark_model`
* `libandroid_tensorflow_lib.lo`
* `libtensorflow_demo.so`
* `libtensorflow_inference.so`

ファイル構造はこんな感じになるはず

```bash
$ tree libs
libs
└── armeabi-v7a
    ├── benchmark_model
    ├── libandroid_tensorflow_lib.lo
    ├── libtensorflow_demo.so
    └── libtensorflow_inference.so
```


# jcenterからTensorFlowのAARを読み込むよう設定
まず、Android StudioでAndroidプロジェクトをOpen。
Gradleのアップデートの表示が出た場合はUpdate。

ここが重要ですが、TensorFlowはjcenterからAAR(ライブラリ)を読み込めるようになっています。 (ここ、もっとREADMEで強調してほしかった)

デフォルトではbazelを使ってビルドするように設定されているため、それを変更。

`<project root>/build.gradle: 43行目`

```bash
# bazelをnoneに変更
def nativeBuildSystem = 'none'
```

エディター上部に`Sync now`と表示されたら、それをクリック。

# ビルド&実行
以上で設定は終了です。
プロジェクトをBuild&Runしてみてください。

うまくいっていれば、Android端末に以下3つのActivityが表示されているはず。

* TF Classify
* TF Detect
* TF Stylize


もし、

* `エラー: パッケージorg.tensorflow.contrib.androidは存在しません`
* `エラー: シンボルを見つけられません。 シンボル:   クラス TensorFlowInferenceInterface`

のようなエラーが表示される場合は、AARがまだ読み込まれていません。

以下の記事を参考にAARを読み込んでください。
[http://qiita.com/icchi_h/items/8ce738ce8511ef69c799](http://qiita.com/icchi_h/items/8ce738ce8511ef69c799#%E5%A4%96%E9%83%A8%E3%83%A9%E3%82%A4%E3%83%96%E3%83%A9%E3%83%AA%E3%81%8C%E8%AA%AD%E3%81%BF%E8%BE%BC%E3%81%BE%E3%82%8C%E3%81%AA%E3%81%84%E5%A0%B4%E5%90%88%E3%81%AE%E5%AF%BE%E5%87%A6%E6%B3%95)

TF Classifyを実行した様子。
カメラ映像から1000クラスの認識結果が表示されます。
<img height="720px" src="https://qiita-image-store.s3.amazonaws.com/0/135313/8e43f8f5-12ae-4fb2-24bb-541426d0abe3.jpeg">


# [Option] TF Classify以外のアプリを削除
これから開発を始めるにあたり、一度プロジェクトを最小構成にしたかったので、TF Classify以外のアプリをプロジェクトから取り除きました。以下はその際に行った処理です。

```bash
# assetsの削除
cd assets/
rm -r multibox_location_priors.txt multibox_model.pb stylize_quantized.pb thumbnails

# コードの削除
cd ../src/org/tensorflow/demo/
rm -r DetectorActivity.java LegacyCameraConnectionFragment.java StylizeActivity.java TensorFlowMultiBoxDetector.java TensorFlowYoloDetector.java tracking env/BorderedText.java env/SplitTimer.java env/Size.java
```

* `AndroidManifest.xml: 45~61行目`
* `ClassifierActivity.java: 35行目`
* `ClassifierActivity.java: 84行目`
* `ClassifierActivity.java: 103~104行目`
* `ClassifierActivity.java: 215行目`
* `ClassifierActivity.java: 317行目` (if文を削除して中身のインデント上げる)
* `ClassifierActivity.java: 334~336行目`
* `download-models.gradle: 12行目`配列から以下の要素を削除
    * `'mobile_multibox_v1a.zip'`
    * `'stylize_v1.zip'`


# Reference
* <https://github.com/tensorflow/tensorflow/tree/master/tensorflow/examples/android>
* <https://github.com/tensorflow/tensorflow/tree/master/tensorflow/contrib/android>
* <https://stackoverflow.com/questions/45529767/no-implementation-found-for-void-org-tensorflow-demo-env-imageutils>