Android Gradle Pluginをv8.7.3へアップデートしてみた
株式会社ココナラアプリ開発グループ、Androidチームの長谷山です。
今回は、ココナラAndroidアプリにおけるAndroid Gradle Plugin (AGP) のバージョンアップ対応についてご紹介します。
背景
ココナラのAndroidアプリでは、Android14対応時にAGPを8.0.0までアップデートしました。
当初、We recommend using a newer Android Gradle plugin to use compileSdk = 34
の警告を消すためにAGP8.1.1までアップデートを検討しましたが、androidx.lifecycleのバージョンが推移的依存関係によりアップデートされてしまい、影響範囲が広くなりすぎるという問題により見送られました。
その後、しばらくAGPのアップデートは行われていませんでした。
しかし、2025年夏に予定されているAndroid15への対応を見据えると、AGPを最低でも8.6.1までアップデートする必要があることがわかっていたので、2024年11月より施策開発の合間を利用して、段階的にアップデート作業を進めることにしました。
アップデート対応リリースフロー
当時、Android Studio Ladybugが最新バージョンであり、AGP Upgrade Assistantを利用して最新の8.7.3まで上げる計画を立てました。
- 隙間時間を利用して複数人で対応を行う
- 影響範囲が広範囲に及ぶ
- その他リリースの差分取り込みが発生する
これらの点を踏まえ、リリースをAGP8.2.2対応と、AGP8.7.3対応の2段階に分割することにしました。
8.2.2で分割した主な理由は、後述するKotlinのバージョンアップによる影響が大きいと判断したためです。
調査
AGPアップデートにあたり、主に以下の項目について調査・確認を行いました。
- ビルドが正常に通るか
- 新たなWarningが発生していないか
- 非推奨 (deprecated) なAPIの利用が増えていないか
- 推移的依存関係によってライブラリのバージョンが意図せず更新されていないか
- 使用しているライブラリが、アップデート後のAGPバージョンとの互換性をサポートしているか
AGPをマイナーバージョンごとに順次アップデートし、その都度上記の項目について調査を実施しました。
起動確認は各アップデート後に都度行いましたが、本格的なQAはリリース分が完了してから行う方針としました。
ビルドエラー
AGP8.1.4へのアップデート時には、androidx.lifecycleのバージョンが2.6.1に上がった影響により、以下の3点について対応が必要となりました。
- androidx.lifecycle.Observerの引数がnonNullに変更された
- androidx.lifecycle.Transformationsが削除された
- androidx.lifecycle.ViewTreeLifecycleOwnerが削除された
AGP8.2.2へのアップデート時には、Kotlinのバージョンが1.9.0に上がった影響により、以下の3点について対応が必要となりました。
- Kotlinを1.9.25へアップデート
- Kotlinアップデートに伴い、Hiltを2.52、Hilt compilerを1.2.0へアップデート
- Kotlinアップデートに伴い、Composeを1.5.15へアップデート
Warning、deprecated
ビルド時に表示されるWarningおよびdeprecatedなAPIの利用について、以前のAGPバージョンと比較し、新たに追加されたものに対して修正を行いました。
例えば、build.gradle.ktsで使用しているproject.buildDirがdeprecatedになり、project.layout.buildDirectory.get()に修正した等になります。
推移的依存関係によるライブラリのアップデート
./gradlew app:dependencies
コマンドの出力結果を以前のAGPバージョンと比較し、ライブラリのバージョンが上がっているものや、プロジェクト内のバージョンカタログで定義されているバージョンと差異があるものを特定し、必要に応じてバージョンを調整しました。
その際、ライブラリのリリースノートを確認し、影響を受ける変更が含まれている場合はコードの修正を行いました。依存関係にあるさらに深い階層のライブラリも確認する必要があり、この作業に最も時間がかかりました。
ライブラリのAGPバージョンの互換性対応
使用しているライブラリのリリースノートを確認し、特定のAGPバージョンとの互換性に関する記述がないかをチェックしました。互換性について言及されているライブラリについては、可能な範囲で最新バージョンへのアップデートを実施しました。
例えば、FirebaseのCrashlytics Gradle Plugin v2.9.3が該当します
つまずいたところ
今回のAGP対応では、AGP 8.4.2へのアップデート時に2つの予期せぬ問題が発生し、対応に時間を要しました。
アプリ起動時にfirebase.perfのremoteConfigManagerでクラッシュが発生
FATAL EXCEPTION: AsyncTask #1
java.lang.ExceptionInInitializerError
at com.google.firebase.perf.config.RemoteConfigManager.getInstance(RemoteConfigManager.java:119)
at com.google.firebase.perf.config.ConfigResolver.<init>(ConfigResolver.java:78)
Caused by: java.lang.IllegalStateException: Default FirebaseApp is not initialized in this process
at com.google.firebase.FirebaseApp.getInstance(FirebaseApp.java:179)
at com.google.firebase.perf.config.RemoteConfigManager.getInitialStartupMillis(RemoteConfigManager.java:91)
このクラッシュの原因はcom.google.gms.google-servicesのバージョンが古かったせいでした。バージョンを4.4.2にアップデートすることで問題は解消されました。
当初、firebase.perf.config.RemoteConfigManagerやFirebaseApp.getInstance周辺を重点的に調査していたため、原因の特定に時間がかかってしまいました。
R8ビルドで特定の画面に遷移するとクラッシュが発生
Fatal Exception: java.lang.RuntimeException
Failed to invoke constructor 'hoge.fuga.class()' with no args
Caused by java.lang.NullPointerException
hoge.fuga.class.<init> (piyo.kt:11)
java.lang.reflect.Constructor.newInstance0 (Constructor.java)
java.lang.reflect.Constructor.newInstance (Constructor.java:343)
com.google.gson.internal.ConstructorConstructor$9.construct (ConstructorConstructor.java:297)
このクラッシュは、gson.fromJson(String json, Type typeOfT)を使用している箇所で、引数なしのコンストラクタが存在しないというエラー内容でした。
詳細な原因特定には至りませんでしたが、AGPのアップデートに伴いR8の最適化処理が変更され、本来保持されるべきコンストラクタが削除された可能性が考えられます。
問題が発生していたhoge.fuga.classはセカンダリコンストラクタを持つクラスであり、プライマリコンストラクタのみを持つように修正することで問題を回避できましたが、今後同様のケースが発生する可能性を考慮し、proguardの設定を追加することで対応しました。
該当箇所以外のクラスでも発生する可能性があるためR8の圧縮率は下がってしまいますが、パッケージ配下に対して適用しました。
-keepclassmembers class hoge.fuga.** {
<init>(...);
}
まとめ
今回はココナラAndroidアプリにおけるAGP8.7.3へのアップデート対応の内容をご紹介しました。
特に、今回つまずいた2つのポイントが、同様の問題に直面している方の助けになれば幸いです。
執筆時点でAGPの最新バージョンはすでに8.9となっています。
今後は、ライブラリやAGPアップデートによる大規模なリリースを避けるため、より細やかなバージョンアップを継続的に実施していく予定です。
ココナラでは、一緒に事業のグロースを推進していただける様々な領域のエンジニアを募集しています。
アプリ開発だけでなく、フロントエンド領域・バックエンド領域などでも積極的にエンジニア採用を行っています。少しでも興味を持たれた方がいましたら、エンジニア採用ページをご覧ください。
Discussion