いつもぶつかって何となく調べて解決してきたAndroid周りの対応

# 前置き
- いつも同じようなエラーが発生する……
- 多分Unityのversion upしたタイミングな気がしている……
- でもその度調べて解決してるが、結局いつも原因忘れてしまっている……

# 環境
- Unity2019.4.18f1
- GoogleMobileAds-v5.4.0
- Android Studio 4.1.3


# 結論
- JDKのバージョンをテキトーなやつ指定してるとUnityでエラーになる場合がある

# 事象
- GoogleMobileAdsを更新したので、Android Force Resolveを再度実施しようとした
- そうしたら以下のようにエラーが発生……


```sh
java.lang.NoClassDefFoundError: Could not initialize class org.codehaus.groovy.vmplugin.v7.Java7
	at org.codehaus.groovy.vmplugin.VMPluginFactory.<clinit>(VMPluginFactory.java:43)
	at org.codehaus.groovy.reflection.GroovyClassValueFactory.<clinit>(GroovyClassValueFactory.java:35)
	at org.codehaus.groovy.reflection.ClassInfo.<clinit>(ClassInfo.java:109)
	at org.codehaus.groovy.reflection.ReflectionCache.getCachedClass(ReflectionCache.java:95)
	at org.codehaus.groovy.reflection.ReflectionCache.<clinit>(ReflectionCache.java:39)
	at org.codehaus.groovy.runtime.metaclass.MetaClassRegistryImpl.registerMethods(MetaClassRegistryImpl.java:209)
	at org.codehaus.groovy.runtime.metaclass.MetaClassRegistryImpl.<init>(MetaClassRegistryImpl.java:107)
	at org.codehaus.groovy.runtime.metaclass.MetaClassRegistryImpl.<init>(MetaClassRegistryImpl.java:85)
	at groovy.lang.GroovySystem.<clinit>(GroovySystem.java:36)
	at org.codehaus.groovy.runtime.InvokerHelper.<clinit>(InvokerHelper.java:86)Reporting analytics data: /androidresolver/resolve/gradle/failed/fetch?unityVersion=2019.4.18f1&unityPlatform=OSXEditor&installSource=upm&version=1.2.164&scope= 'Android Resolver: Gradle Resolve: Tool Extraction Failed'
ERROR: Gradle failed to fetch dependencies.
```


# 原因と解決方法
## 原因
- Javaのversionが`14.0.1`だったのがダメそう。`1.8.0`だと大丈夫そう

## 解決方法
### 大丈夫なJDKはどこ？
- Android Studioのjava versionを確認する

```sh
$ /Applications/Android\ Studio.app/Contents/jre/jdk/Contents/Home/bin/java -version
openjdk version "1.8.0_242-release"
OpenJDK Runtime Environment (build 1.8.0_242-release-1644-b3-6915495)
OpenJDK 64-Bit Server VM (build 25.242-b3-6915495, mixed mode)
```
→ 大丈夫そうなのでこれを指定する。ただし、[AndroidStudio4.2以降だとJDK11がバンドルされている](https://developer.android.com/studio/releases?hl=ja#4.2-bundled-jdk-11)とのこと。

- UnityHub使っていれば、よしなに1.8.0をinstallされているみたいなので、AndroidStudio側も1.8.0でない場合、こちらのパスをJAVA_HOMEに指定しておくのが良さそう（あんまりキレイではないが……）


```sh
/Applications/Unity/Hub/Editor/2020.3.25f1/PlaybackEngines/AndroidPlayer/OpenJDK/bin/java -version
```

### UnityでJDK指定
- Preferences > External Toolsを開く
- Android > JDKにAndroid StudioのJDKパス（/Applications/Android Studio.app/Contents/jre/jdk/Contents/Home）を参照するようにする（`※直接指定だとできなかったので、Browseから指定`）
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/87713/f8dc69dc-3f34-80b0-3c50-bdd6dcf4866a.png)

#### ちょっと詰まった点
- PreferencesのBrowseからだとAndroidStudio配下を参照することができなかったので、`open /Applications/Android\ Studio.app/Contents/jre`とかでFinderでAndroidStudio配下を開く
- jdkのディレクトリをひとまずサイドメニューのよく使う項目に突っ込む
- PreferencesのBrowseからよく使う項目のショートカットより選択する

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/87713/dbd393e5-573c-7aec-5726-4b10bf75d7d0.png)

## 上記でもダメな場合の解決方法
- 上記の解決方法で解決してたけど、たまにUnity上で突然同じエラーでダメになってしまうケースにぶつかった
- 自分の場合は、どうもシステム側？の`usr/bin/java`を参照していたみたいだった
- 上記の通り、UnityのPreferencesでも、JAVA_HOMEのパスとかも通しているが、どうにも変なルートでシステム側を参照しているみたいだった
- そして、システム側もどうやってインストールされたかが不明（システム環境設定にも、brew listにもいない状況）なので、アンインストールもしづらい
- UnityでもFlutterでもバンドルされたJDKを基本参照するので、システム側は使わないと割り切り、1.8系を以下のようにインストールして、Unity再起動で無事解決！

```sh
brew tap AdoptOpenJDK/openjdk
brew install --cask adoptopenjdk8
```

## ここまででもダメだった場合の解決法(2022/5/15追記)
- AdMobじゃないけど、Androidビルド時に、同じエラーに出会した
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/87713/ff35dd86-69e8-4069-021b-704d0d79f7dc.png)
```sh
ommandInvokationFailure: Failed to update Android SDK package list.
/Applications/Unity/Hub/Editor/2021.3.2f1/PlaybackEngines/AndroidPlayer/SDK/tools/bin/sdkmanager --list

stderr[
Picked up JAVA_TOOL_OPTIONS: -Dfile.encoding=UTF-8
Exception in thread "main" java.lang.NoClassDefFoundError: javax/xml/bind/annotation/XmlSchema
	at com.android.repository.api.SchemaModule$SchemaModuleVersion.<init>(SchemaModule.java:156)
	at com.android.repository.api.SchemaModule.<init>(SchemaModule.java:75)
	at com.android.sdklib.repository.AndroidSdkHandler.<clinit>(AndroidSdkHandler.java:81)
	at com.android.sdklib.tool.sdkmanager.SdkManagerCli.main(SdkManagerCli.java:73)
	at com.android.sdklib.tool.sdkmanager.SdkManagerCli.main(SdkManagerCli.java:48)
Caused by: java.lang.ClassNotFoundException: javax.xml.bind.annotation.XmlSchema
	at java.base/jdk.internal.loader.BuiltinClassLoader.loadClass(BuiltinClassLoader.java:641)
	at java.base/jdk.internal.loader.ClassLoaders$AppClassLoader.loadClass(ClassLoaders.java:188)
	at java.base/java.lang.ClassLoader.loadClass(ClassLoader.java:520)
	... 5 more
]
... 
```

- 今まで同様、sdkmanagerなどのパスはちゃんと通ってそう、またターミナル上からだと同じコマンドでも通る状況
- ターミナルから`java -version`を実行しても、ちゃんと1.8.0でパスは通ってそう
- javaの状況を改めて確認すると、1.8系以外にまだ生き残りがいそう……
```sh
$ /usr/libexec/java_home -V      
Matching Java Virtual Machines (5):
    17.0.2 (x86_64) "Eclipse Temurin" - "Eclipse Temurin 17" /Library/Java/JavaVirtualMachines/temurin-17.jdk/Contents/Home
    16.0.1 (x86_64) "AdoptOpenJDK" - "AdoptOpenJDK 16" /Library/Java/JavaVirtualMachines/adoptopenjdk-16.jdk/Contents/Home
    14.0.1 (x86_64) "Oracle Corporation" - "OpenJDK 14.0.1" /Library/Java/JavaVirtualMachines/jdk-14.0.1.jdk/Contents/Home
    1.8.0_302 (x86_64) "Eclipse Temurin" - "Eclipse Temurin 8" /Library/Java/JavaVirtualMachines/temurin-8.jdk/Contents/Home
    1.8.0_292 (x86_64) "AdoptOpenJDK" - "AdoptOpenJDK 8" /Library/Java/JavaVirtualMachines/adoptopenjdk-8.jdk/Contents/Home
```
- 1.8.0以外とは決別する覚悟をしたので、1.8系以外は全部削除
```sh
$ sudo rm -rf /Library/Java/JavaVirtualMachines/adoptopenjdk-16.jdk 
$ sudo rm -rf /Library/Java/JavaVirtualMachines/temurin-17.jdk
$ sudo rm -rf /Library/Java/JavaVirtualMachines/jdk-14.0.1.jdk 
```
- ビルド成功！今度こそ、もう発生しないことを願う……



# 解決までの道のり
- google先生に聞くとgradleのバージョンが低いと出るかもとかあり、3.4.0を参照していそうだったので、確かに古そうと、updateを試みる

## 現状のgradleのバージョンを確認
```sh
cat /Applications/Unity/PlaybackEngines/AndroidPlayer/Tools/GradleTemplates/baseProjectTemplate.gradle
```

```gradle
allprojects {
    buildscript {
        repositories {**ARTIFACTORYREPOSITORY**
            google()
            jcenter()
        }

        dependencies {
            // If you are changing the Android Gradle Plugin version, make sure it is compatible with the Gradle version preinstalled with Unity
            // See which Gradle version is preinstalled with Unity here https://docs.unity3d.com/Manual/android-gradle-overview.html
            // See official Gradle and Android Gradle Plugin compatibility table here https://developer.android.com/studio/releases/gradle-plugin#updating-gradle
            // To specify a custom Gradle version in Unity, go do "Preferences > External Tools", uncheck "Gradle Installed with Unity (recommended)" and specify a path to a custom Gradle version
            classpath 'com.android.tools.build:gradle:3.4.0'
            **BUILD_SCRIPT_DEPS**
        }
    }
~
```
3.4.0っぽい！古い！

## projectをexportするとgradleのアップデートが流れでできるらしい
- Build Settingで、Export Projectをチェック
- Exportボタンになるので押下
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/87713/8877a6f8-99ef-e11b-42c6-f5ae6cb9c6ae.png)



## だがしかしexportできない！
### その1. export時にエラー
#### 原因と解決方法
##### 原因
- export先のpathはUnityのproject直下だとダメそう……

```sh
Invalid build path: /users/nir/git/daydayday
UnityEngine.GUIUtility:ProcessEvent(Int32, IntPtr) (at /Users/bokken/buildslave/unity/build/Modules/IMGUI/GUIUtility.cs:197)
```

##### 解決方法
- とりあえずprojectの上の方の階層をテキトーに指定でOK

### その2. java.lang.NoClassDefFoundError
#### 原因と解決方法
##### 原因
- こんな感じのエラーが発生

```sh
CommandInvokationFailure: Failed to update Android SDK package list.
/Users/nir/Library/Android/sdk/tools/bin/sdkmanager --list

stderr[
Picked up JAVA_TOOL_OPTIONS: -Dfile.encoding=UTF-8
Exception in thread "main" java.lang.NoClassDefFoundError: javax/xml/bind/annotation/XmlSchema
	at com.android.repository.api.SchemaModule$SchemaModuleVersion.<init>(SchemaModule.java:156)
	at com.android.repository.api.SchemaModule.<init>(SchemaModule.java:75)
	at com.android.sdklib.repository.AndroidSdkHandler.<clinit>(AndroidSdkHandler.java:81)
	at com.android.sdklib.tool.sdkmanager.SdkManagerCli.main(SdkManagerCli.java:73)
	at com.android.sdklib.tool.sdkmanager.SdkManagerCli.main(SdkManagerCli.java:48)
Caused by: java.lang.ClassNotFoundException: javax.xml.bind.annotation.XmlSchema
	at java.base/jdk.internal.loader.BuiltinClassLoader.loadClass(BuiltinClassLoader.java:602)
	at java.base/jdk.internal.loader.ClassLoaders$AppClassLoader.loadClass(ClassLoaders.java:178)
	at java.base/java.lang.ClassLoader.loadClass(ClassLoader.java:522)
	... 5 more
]
stdout[

]
exit code: 1
```

- terminalで以下を打つと、確かに同じエラーが発生する……

```sh
/Users/nir/Library/Android/sdk/tools/bin/sdkmanager --list
```

- こちらの資料を参考に、javaの設定を見直すことに
    - [android: sdkmanagerを起動すると、NoClassDefFoundErrorで起動できない](https://www.ninton.co.jp/archives/2723)


##### 解決方法
- 現状のバージョンを確認

```sh
$  java -version
openjdk version "14.0.1" 2020-04-14
OpenJDK Runtime Environment (build 14.0.1+7)
OpenJDK 64-Bit Server VM (build 14.0.1+7, mixed mode, sharing)

$  which java
/usr/bin/java
```

- Android Studio側のバージョンを確認

```sh
$ /Applications/Android\ Studio.app/Contents/jre/jdk/Contents/Home/bin/java -version
openjdk version "1.8.0_242-release"
OpenJDK Runtime Environment (build 1.8.0_242-release-1644-b3-6915495)
OpenJDK 64-Bit Server VM (build 25.242-b3-6915495, mixed mode)
```

- bashrcに設定＆適用（`source ~/.bashrc`）

```bash:~/.bashrc
export JAVA_HOME=/Applications/Android\ Studio.app/Contents/jre/jdk/Contents/Home
export PATH=$JAVA_HOME/bin:$PATH
```

- 変更されたかを確認＆再度sdkmanagerの実行確認

```sh
$ java -version
openjdk version "1.8.0_242-release"
OpenJDK Runtime Environment (build 1.8.0_242-release-1644-b3-6915495)
OpenJDK 64-Bit Server VM (build 25.242-b3-6915495, mixed mode)

/Users/nir/Library/Android/sdk/tools/bin/sdkmanager --list
```

ここまで対応して、gradleのアップデートをしていない状態で、ふと再度Force Resolveしたら今度は行けた！なので、JDKの設定が悪いと判断した流れ。


# 最後に
- 回り道した感じがしたけど、解決できてよかった……
- Unityのアップデートの度同じエラーに出会した気がするので、JDKの設定が原因と考えると何か納得