macOSで Android向けの OpenCVと OpenCV Contribをビルドする

## この記事を読む前に

https://github.com/quickbirdstudios/opencv-android

ここで各バージョンの contrib入りパッケージが提供されているので、本当にビルドが必要なのか検討すること。

## 環境

NDK : 21.3.6528147
Java : Oracle JDK 1.8.0_121

Javaを Homebrewの openjdkで試したのだがうまく行かなかった。この辺の解決方法を調べたい。

## 環境変数

環境変数 ANDROID_SDK, ANDROID_NDK, ANDROID_NDK_HOMEをセットする。

```
    export ANDROID_SDK=/Applications/adt-bundle-mac-x86_64/sdk
    export ANDROID_NDK=/Applications/adt-bundle-mac-x86_64/sdk/ndk/21.3.6528147
    export ANDROID_NDK_HOME=$ANDROID_NDK
```

## ビルド
あとは以下の手順で git cloneしてビルド。時間はそれなりにかかる。

``` 
mkdir ~/X
cd ~/X

git clone https://github.com/opencv/opencv.git
git clone https://github.com/opencv/opencv_contrib.git

cd opencv/platforms/android

./build_sdk.py --extra_modules_path ~/X/opencv_contrib/modules ~/X/opencv/build ~/X/opencv
```

```~/X/opencv/build/OpenCV-android-sdk``` 以下にライブラリが生成される。


Oracle JDKを使っているのなら作業はここまで。

以下、 Homebrewの openjdkを使っている場合の苦労の記録。

## トラブルシューティング

### openjdkでビルドできない
Oracle JDKだと上記の手順で問題ないが、 Homebrewの openjdkを使っているとエラーが出る。

```
...
Starting Build

FAILURE: Build failed with an exception.

* What went wrong:
Could not initialize class org.codehaus.groovy.runtime.InvokerHelper
...
```

使用する gradleを新しいものにして回避できた。

```gradle-wrapper/gradle/wrapper/gradle-wrapper.properties
#distributionUrl=https\://services.gradle.org/distributions/gradle-5.6.4-all.zip
distributionUrl=https\://services.gradle.org/distributions/gradle-6.4.1-all.zip
```

### ビルド時にプロキシを越えられない

社内プロキシに守られている環境依存の話。

```
...
Downloading https://services.gradle.org/distributions/gradle-6.4.1-all.zip

Exception in thread "main" java.io.IOException: Unable to tunnel through proxy. Proxy returns "HTTP/1.1 407 Proxy Authentication Required"
	at java.base/sun.net.www.protocol.http.HttpURLConnection.doTunneling(HttpURLConnection.java:2185)
...
```

回避するには gradle.propertiesを修正する。

```gradle-wrapper/gradle.properties
systemProp.jdk.http.auth.tunneling.disabledSchemes=
systemProp.jdk.http.auth.proxying.disabledSchemes=

systemProp.http.proxyHost=x.x.x.x
systemProp.http.proxyPort=xxxx
systemProp.http.proxyUser=<your_username>
systemProp.http.proxyPassword=<your_password>

systemProp.https.proxyHost=x.x.x.x
systemProp.https.proxyPort=xxxx
systemProp.https.proxyUser=<your_username>
systemProp.https.proxyPassword=<your_password>
```

### [作業中] まだエラーが出る。サンプルのビルドに失敗

```
...
Parsing the SDK, no caching allowed
SDK initialized in 8 ms
Using incremental javac compilation for :15-puzzle debug.

FAILURE: Build failed with an exception.

* What went wrong:
A problem occurred configuring project ':15-puzzle'.
> Failed to notify project evaluation listener.
   > 'org.gradle.api.file.RegularFileProperty org.gradle.api.file.ProjectLayout.fileProperty(org.gradle.api.provider.Provider)'
...
```

Androidアプリのビルドに使用する gradleのバージョンが古いか、ローカル環境に入っていないことが原因?

```build/o4a/opencv_android/build.gradle
    dependencies {
        classpath 'com.android.tools.build:gradle:3.2.1'

```

[調査中]

```opencv/cmake/android/android_gradle_projects.cmake``` にそれらしい記述

```android_gradle_projects.cmake
# https://developer.android.com/studio/releases/gradle-plugin
set(ANDROID_GRADLE_PLUGIN_VERSION "3.2.1" CACHE STRING "Android Gradle Plugin version (3.0+)")
message(STATUS "Android Gradle Plugin version: ${ANDROID_GRADLE_PLUGIN_VERSION}")

set(ANDROID_COMPILE_SDK_VERSION "26" CACHE STRING "Android compileSdkVersion")
...
```

ここを6.5に書き換えてみる → だめ


https://qiita.com/tktcorporation/items/c8e2bbe7e32be193be83 を参考に、

 * ローカル環境で Android Studioのプロジェクトを新規作成
 * 新規作成プロジェクトの gradle/wrapper/以下、 gradle-wrapper.jar, gradle-wrapper.propertiesを opencv/platforms/android/gradle-wrapperの下にコピー


これでもまだ駄目

```
...
* What went wrong:
A problem occurred configuring project ':15-puzzle'.
> Failed to notify project evaluation listener.
   > 'org.gradle.api.file.RegularFileProperty org.gradle.api.file.ProjectLayout.fileProperty(org.gradle.api.provider.Provider)'

* Try:
Run with --stacktrace option to get the stack trace. Run with --debug option to get more log output. Run with --scan to get full insights.
...
```


...サンプルをビルドしないでは??

```
./build_sdk.py --no_samples_build --extra_modules_path ~/X/opencv_contrib/modules ~/X/opencv/build ~/X/opencv

...

> Task :opencv:compileDebugJavaWithJavac FAILED
Caching disabled for task ':opencv:compileDebugJavaWithJavac' because:
  Build cache is disabled
Task ':opencv:compileDebugJavaWithJavac' is not up-to-date because:
  No history is available.
The input changes require a full rebuild for incremental task ':opencv:compileDebugJavaWithJavac'.
Compiling with source level 1.6 and target level 1.6.
Full recompilation is required because no incremental change information is available. This is usually caused by clean builds or changing compiler arguments.
file or directory '/Users/nunokawa/X/opencv/build/o4a/opencv_android/opencv/src/debug/java', not found
Compiling with JDK Java compiler API.
エラー: ソース・オプション6は現在サポートされていません。7以降を使用してください。
エラー: ターゲット・オプション6は現在サポートされていません。7以降を使用してください。
:opencv:compileDebugJavaWithJavac (Thread[Execution worker for ':' Thread 4,5,main]) completed. Took 1.014 secs.

FAILURE: Build failed with an exception.

...
```

...(ヽ´ω`) つらい