はじめに
前回のポストから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.** { *; }
所感
実は、デバッグビルドだと問題なく動いていたようで、その確認を怠ったために切り分けが長引いてしまいました。
ビルド周りは、出力先プラットフォームが利用する技術への理解が必要になるので、なかなか大変です…。