Android Gradle Plugin (AGP) を7から8へアップデートした際に、BuildConfig
と R
クラスの生成に関する変更点により、ビルドエラーが発生しました。その時のメモを備忘録として書いておきます。
AGP8のリリースノートは以下にあります。
https://developer.android.com/build/releases/past-releases/agp-8-0-0-release-notes
このサイトに記載されている「互換性のない変更」のうち、手元の環境ではandroid.defaults.buildfeatures.buildconfig
と android.nonTransitiveRClass
が該当していました。
1. BuildConfigのデフォルト生成が停止
問題点
AGP8では、BuildConfig
クラスがデフォルトで生成されなくなりました。そのため、以下のように BuildConfig.DEBUG
を使ってデバッグ時のみ特定の処理を実行していたコードがコンパイルエラーとなります。
if (BuildConfig.DEBUG) {
// デバッグ時のみの処理
Log.d("MyApp", "Debug mode");
}
エラーメッセージ例:
error: cannot find symbol
if (BuildConfig.DEBUG) {
^
symbol: variable DEBUG
location: class BuildConfig
(解決策1) 個別モジュールごとに buildConfig を有効化
各モジュールの build.gradle.kts (または build.gradle) ファイルで、buildFeatures 内の buildConfig を true に設定します。
android {
buildFeatures {
buildConfig = true
}
}
この方法では、必要なモジュールのみで BuildConfig を生成できるため、ビルド時間の増加を最小限に抑えられます。
(解決策2) gradle.properties で設定 (非推奨)
プロジェクトルートの gradle.properties ファイルに以下の行を追加することで、全てのモジュールで BuildConfig を生成できます。
android.defaults.buildfeatures.buildconfig=true
この方法は非推奨であり、以下の通りAGP9で削除される予定なので、暫定対応として対応しておきます。
The option setting 'android.defaults.buildfeatures.buildconfig=true' is deprecated.
The current default is 'false'.
It will be removed in version 9.0 of the Android Gradle plugin.
You can resolve this warning in Android Studio via Refactor > Migrate BuildConfig to Gradle Build Files
2. Rクラスの生成範囲の変更
問題点
AGP8では、デフォルトで現在のモジュールで定義されたリソースのRクラスのみが作成されるようになりました。つまり、マルチモジュール構成で、他のモジュールで定義されたリソースを Rクラス経由で参照できなくなりました。
例えば、feature モジュールから common モジュールで定義された文字列リソースを参照しようとすると、以下のようなコンパイルエラーが発生します。
// featureモジュールのコード
getString(R.string.foo) // commonモジュールで定義された文字列リソース
error: cannot find symbol
getString(R.string.foo)
^
symbol: variable string
location: class R
(解決策1) リソースの完全修飾名で参照
参照したいリソースが定義されているモジュールのパッケージ名を明示的に指定します。
// featureモジュールからcommonモジュールのRを参照
getString(com.example.common.R.string.foo)
この方法であれば、ビルド時間に影響を与えることなく問題を解決できます。しかし、すべてのリソース参照を完全修飾名に変更する必要があるため、修正コストが大きくなる可能性があります。
(解決策2) gradle.properties で設定 (ビルド時間増加)
gradle.properties ファイルに以下の行を追加することで、以前の挙動(全てのモジュールのリソースを参照できる R クラスを生成)に戻すことができます。
android.nonTransitiveRClass=false
ただし、この方法はビルド時間が増加するデメリットがあります。特に大規模なプロジェクトでは、ビルド時間の増加が顕著になる可能性がありますが、手元のプロジェクトではこちらの方法を採用しました。