🔴

AGPを8.4に上げると「Missing classes detected while running R8. 〜」というビルドエラーが出る

2024/05/27に公開

事象

AndroidStudio JellyfishのStableが出たので、早速アップデートをして、一緒にAGP(Android gradle plugin)も8.4.0に上げたらビルドエラーが出た。

具体的には下記のようなエラーが出る。

Missing classes detected while running R8. Please add the missing classes or apply additional keep rules that are generated in (module)/build/outputs/mapping/release/missing_rules.txt.

NoClassDefFoundErrorが出ることもある。

環境

  • AndroidStudio Jellyfish
  • AGP8.4.0(上げる前は8.3.2)
  • マルチモジュール構成のプロジェクト

解決策

マルチモジュールにおいて、ライブラリモジュールでは難読化をしないようisMinifyEnabled=falseにする。(AARとして公開する、かつ、先に難読化したい場合は別)
つまり、アプリモジュールのみでisMinifyEnabled=trueにする。
ライブラリモジュール内でproguardルールを指定したい場合は、consumerProguardFilesで、そのモジュールのconsumer-rules.proを指定する

https://developer.android.com/studio/projects/android-library?hl=ja#Considerations

原因

AGP8.4の更新内容に書いてある。
ドキュメントを見ると、AGP8.4では、「ライブラリのクラスが縮小される」という更新がある。

https://developer.android.com/build/releases/gradle-plugin?hl=ja#library-classes-shrunk

アプリが圧縮バージョンの Android ライブラリ サブプロジェクトに依存している場合、APK には圧縮された Android ライブラリ クラスが含まれます。APK に欠落しているクラスがある場合、ライブラリ保持ルールの調整が必要になることがあります。

以前の動作に戻すには、gradle.properties ファイルで android.disableMinifyLocalDependenciesForLibraries を設定し、バグを報告してください。AGP の今後のバージョンでは、このフラグは削除されます。

実際に、 disableMinifyLocalDependenciesForLibrariesを設定するとビルドが通った。
このフラグは削除されるため、根本対応をする必要がある。

解説

ライブラリモジュールのドキュメントに以下の記載がある。

ライブラリ モジュールに ProGuard ファイルを埋め込むと、ライブラリに依存するアプリ モジュールで、ライブラリを使用するために ProGuard ファイルを手動で更新する必要がなくなります。Android Studio のビルドシステムでアプリをビルドする際には、アプリ モジュールとライブラリの両方のディレクティブが使用されます。したがって、ライブラリで別途コード圧縮ツールを実行する必要はありません。

APK にコンパイルされ AAR を生成しないマルチモジュール ビルドにライブラリ モジュールが含まれている場合は、ライブラリを使用するアプリ モジュールでのみコード圧縮を実行してください。ProGuard ルールとその使用方法について詳しくは、アプリの圧縮、難読化、最適化をご覧ください。

https://developer.android.com/studio/projects/android-library?hl=ja#Considerations

まとめると、以下になる。

  • ライブラリモジュールは、アプリモジュールで難読化指定してれば一緒に難読化される
    • proguardルールを指定したければ、consumerProguardFilesを設定すれば良い
    • そのため、圧縮した状態のAARを配信したい場合を除き、単体でコード圧縮ツールを実行する必要はない
  • AARをビルドして公開しない場合は、アプリモジュールでのみコード圧縮をするべき

ちなみに、リファレンスアプリであるnow in androidや、我らのDroidKaigi2023アプリもappモジュールのみに難読化指定をしていた。

調査メモ

エラー発生から解決までのメモ

エラーメッセージの対応

Missing classes detected while running R8. Please add the missing classes or apply additional keep rules that are generated in (module)/build/outputs/mapping/release/missing_rules.txt.

AGP更新を読んでその影響だとは分かったが、直したが分からないので調査していく。

エラーを要約すると「難読化で足りないKeepルールがあるから、missing_rules.txtに出力したよ」とのこと。
missing_rules.txtは下記のようになっている。

# Please add these rules to your existing keep rules in order to suppress warnings.
# This is generated automatically by the Android Gradle plugin.
-dontwarn xxx.yyy.ZZ

dontwarnでクラス名が入っており、これをproguard-rulesに入れれば通りそうである。
しかし、これをモジュールのproguard-rules.proに入れてビルドしても、別のモジュールで同じエラーが出た。
全部直すのは大変なので、他の方法がないか調べていく。

他に発生している人がいないか

同じ事象が起きていないか確認すると、いくつか確認できた。

https://stackoverflow.com/questions/78433844/android-agp-8-4-and-hilt
AGP8.4に関する投稿。appモジュールのみ難読化をtrueにせよとある。

「ライブラリモジュールは難読化すべきでない」のかもしれないと思い、これはAPGは関係なさそうだったので、他の情報がないか調べる。

https://stackoverflow.com/a/50819864
https://stackoverflow.com/a/49048425
これらは数年前の投稿だが、こちらもappモジュールのみ難読化をtrueにすべきと回答がある。

「ライブラリモジュールは難読化すべきでない」の確度が高まったので、改めて公式ドキュメントを探してみる。
consumerProguardFilesマルチモジュールといった単語でドキュメントを探していたら、解説に載せた公式ページの言及を見つけることが出来た。

実際の確認

その後、念の為、ライブラリモジュールが難読化されるか実際に試したが、難読化されることが確認できた。
AGP8.3.2でappモジュールのみにisMinifyEnabled=trueを入れたものと、今まで通り全てのモジュールに入れたものとでアプリサイズ・mapping.txtを確認したところ、ライブラリモジュールが難読化されていることが確認できた。

最後に

今回の調査で、根本的な推奨設定を知ることが出来た。
(個人的には)公式情報が見付けづらいと思ったので、メモとして残しておく。
ご指摘などあればお気軽にコメントください!

Discussion