はじめに
前回のポストから2ヶ月くらい空いてしまいました。
生きてます。ありがたいことに忙しいです。
さて、今回は 含まれているはずの Native Plugin のクラスが AndroidJavaClass で参照出来ない という問題に遭遇したので、備忘録として記します。
現象
Unity 2018.3 でビルドした Android Player が AndroidJavaClass や AndroidJavaObject を利用する箇所で ClassNotFoundException *1 を吐く
java.lang.ClassNotFoundException: android.support.v4.content.ContextCompat
前提
- Unity 2018.3.6f1
- Build Type: Gradle
- 今回 Unity 2018.3 対応する際に Internal から切り替えました
AndroidJavaClassが参照する Java クラスは.aarファイルにて提供される- 利用したいクラスは
android.support.v4.content.ContextCompat
- 利用したいクラスは
調査
最初は「Firebase SDK に同梱される Play Service Resolver によって提供される .jar ファイルや .aar ファイルが古い…?」とか「Gradle に切り替えた *2 コトにより、ライブラリが競合した…?」などの可能性を模索して mainTemplate.gradle をプロジェクト内に置くなどして頑張ってもダメで、途方に暮れていました。
が、ふと「ビルドまでは存在しているクラスが消える」という現象から「あれ?Code Strip 的な動きじゃね?」と思い至り、そっちの方面から調査を再開しました。
んで、調べていると Android Project として Export した際に吐き出される build.gradle 内に以下のような記述を発見しました。
android {
buildTypes {
debug {
minifyEnabled false
useProguard false
}
release {
minifyEnabled true
useProguard true
}
}
}
で、「Proguard の難読化によってクラス名変わった!?」と思い、オプション変えるもダメ。
「何でだよー!」と思い、ダメ元で「 minifyEnabled を false に変える」と「ウゴイタァァァ!!!」
原因
ProGuard を用いた Minify 処理により、 AndroidJavaClass や AndroidJavaObject からしか参照されていないクラスが落とされていた。
AndroidJavaClass や AndroidJavaObject はリフレクション(厳密には違うと思うけど)的な処理であり、コンパイラ的には参照を解決できないために Minify 時に落とされてしまうワケですね。
対策
雑に対応
PlayerSettings の Minify > Release を ProGuard から None に変更する。

カチッと対応
PlayerSettings の Minify > Release は ProGuard のままにし、 User Proguard File を有効にする。

(まだファイルが無ければ)自動生成される proguard-user.txt の内容を以下のようにする。(もっと詳細に指定しても良いかも知れません。)
-keep class android.support.v4.content.** {
*;
}
所感
実は、デバッグビルドだと問題なく動いていたようで、その確認を怠ったために切り分けが長引いてしまいました。
ビルド周りは、出力先プラットフォームが利用する技術への理解が必要になるので、なかなか大変です…。