🤬

AndroidStudio Ladybug 2024.2.1 をインストールするとFlutterプロジェクトのビルドができなくなる問題

2024/12/06に公開

はじめに

この記事では、AndroidStudioの更新をしたときにJDKがバージョンアップされ、Flutterアプリがビルドできなくなった問題を解決するためにいろいろと試みたメモです。

今回、私はJDK21にすることを選びました。結果として結構大変な作業になってしまいました。
しかし、JDK17を維持する選択もあると思います。単にAndroidStudioのバージョンを元に戻すか、JDK17を使い続けるようにFlutter CLIを構成すれば良いです。

https://zenn.dev/pside/articles/f790fbdcac31cf

何らかのトラブルを抱えてここに辿り着き、私と同じようにJDK21を使いたい方は、もしかすると環境によっては全てを試さずとも問題が解決されるかも知れません。必要なものだけ持って帰ってください。

なお、私が遭遇したプロジェクトは概ね以下の構成になっていました。

  • Flutterは現時点(2024/12/06)でそこそこ最新の 3.24.2 を使っています
    • ただしGradleのバージョンは 7.5 でした
  • JDKはもともと17でしたが、21にあげようとしています
  • --dart-define-from-file をNativeレイヤーでも使えるようにするため、以下の記事を参考に環境構築しています

https://zenn.dev/altiveinc/articles/separating-environments-in-flutter

そういう条件があるという前提で、この記事をお読みくださると幸いです。

では、どうぞ!

やったこと①: Gradle wrapperのバージョンを 8.5 にする

現在自分が関与しているFlutterプロジェクトで、急に(※)アプリのビルドがうまくいかなくなってしまった。

% task run  
task: [run:stg:debug] $FLUTTER_COMMAND run --debug --dart-define-from-file=dart_defines/stg.json
Launching lib/main.dart on Pixel 8a in debug mode...

FAILURE: Build failed with an exception.

* What went wrong:
Could not open cp_settings generic class cache for settings file '/Users/***/***/android/settings.gradle' (/Users/***/.gradle/caches/7.5/scripts/ef5p1kofx8s6frrt2h1mqizl6).
> BUG! exception in phase 'semantic analysis' in source unit '_BuildScript_' Unsupported class file major version 65

* Try:
> Run with --stacktrace option to get the stack trace.
> Run with --info or --debug option to get more log output.
> Run with --scan to get full insights.

* Get more help at https://help.gradle.org

BUILD FAILED in 312ms
Running Gradle task 'assembleDebug'...                             807ms

┌─ Flutter Fix ───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┐
│ [!] Your project's Gradle version is incompatible with the Java version that Flutter is using for Gradle.                                                   │
│                                                                                                                                                             │
│ If you recently upgraded Android Studio, consult the migration guide at https://flutter.dev/to/to/java-gradle-incompatibility.                              │
│                                                                                                                                                             │
│ Otherwise, to fix this issue, first, check the Java version used by Flutter by running `flutter doctor --verbose`.                                          │
│                                                                                                                                                             │
│ Then, update the Gradle version specified in /Users/***/***/android/gradle/wrapper/gradle-wrapper.properties to be compatible with that │
│ Java version. See the link below for more information on compatible Java/Gradle versions:                                                                   │
│ https://docs.gradle.org/current/userguide/compatibility.html#java                                                                                           │
│                                                                                                                                                             │
│                                                                                                                                                             │
└─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┘
Error: Gradle task assembleDebug failed with exit code 1
task: Failed to run task "run:stg:debug": exit status 1

・・・なるほど。"Flutter Fix" が示すことは、「プロジェクトのGradleバージョンと、FlutterがGradleで使用しているJavaバージョンが互換性がありません。」ということで、 gradle-wrapper.properties を更新して対応しているJavaのバージョンにあうGradleバージョンにせよ、とのこと。

まずはFlutterが使用しているJavaバージョンを確認します。flutter doctor -v を実行します。

% flutter doctor -v
(snip)
[] Android toolchain - develop for Android devices (Android SDK version 35.0.0)
    • Android SDK at /Users/***/Library/Android/sdk
    • Platform android-35, build-tools 35.0.0
    • ANDROID_HOME = /Users/***/Library/Android/sdk
    • Java binary at: /Users/***/Applications/Android
      Studio.app/Contents/jbr/Contents/Home/bin/java
    • Java version OpenJDK Runtime Environment (build 21.0.3+-79915917-b509.11)
    • All Android licenses accepted.
(snip)

ここで、使用しているOpenJDKのバージョンが、もともと 17 だったはずが 21 になっていることに気がつきました。
「プロジェクトのGradleバージョンと、FlutterがGradleで使用しているJavaバージョンが互換性がありません。」というエラーは、このJDKのバージョンがAndroidStudioのアップデートに連動してあがってしまったことが原因のようです。

JDK17をもつ古いAndroidStudioに戻しても良いのですが、たぶんこれはほっといても勝手に直るものではないと思ったので、しっかり直すことにしました。

というわけで、JDK21に対応したGradleに更新します。
Compatibility Matrix を見ると、JDK21に対応したGradleは 8.5 ということで、以下のように対応します。

diff --git a/android/gradle/wrapper/gradle-wrapper.properties b/android/gradle/wrapper/gradle-wrapper.properties
--- a/android/gradle/wrapper/gradle-wrapper.properties
+++ b/android/gradle/wrapper/gradle-wrapper.properties
@@ -3,3 +3,3 @@
 zipStoreBase=GRADLE_USER_HOME
 zipStorePath=wrapper/dists
-distributionUrl=https\://services.gradle.org/distributions/gradle-7.5-all.zip
+distributionUrl=https\://services.gradle.org/distributions/gradle-8.5-all.zip

これで一件落着・・・とは残念ながらなりませんでした。続く。。。

やったこと②: Android Gradle Pluginのバージョンを 8.7.0 にあげる

実行すると、次は以下のエラーが出ました。

% task run
task: [run:stg:debug] $FLUTTER_COMMAND run --debug --dart-define-from-file=dart_defines/stg.json
Launching lib/main.dart on Pixel 8a in debug mode...
警告: [options] ソース値8は廃止されていて、今後のリリースで削除される予定です
警告: [options] ターゲット値8は廃止されていて、今後のリリースで削除される予定です
警告: [options] 廃止されたオプションについての警告を表示しないようにするには、-Xlint:オプションを使用します。
警告3個

FAILURE: Build failed with an exception.

* What went wrong:
Execution failed for task ':connectivity_plus:compileDebugJavaWithJavac'.
> Could not resolve all files for configuration ':connectivity_plus:androidJdkImage'.
   > Failed to transform core-for-system-modules.jar to match attributes {artifactType=_internal_android_jdk_image, org.gradle.libraryelements=jar, org.gradle.usage=java-runtime}.
      > Execution failed for JdkImageTransform: /Users/***/Library/Android/sdk/platforms/android-34/core-for-system-modules.jar.
         > Error while executing process /Users/***/Applications/Android Studio.app/Contents/jbr/Contents/Home/bin/jlink with arguments {--module-path /Users/***/.gradle/caches/transforms-3/2ede1543dfe14c2f7797fbb7f54ef439/transformed/output/temp/jmod --add-modules java.base --output /Users/***/.gradle/caches/transforms-3/2ede1543dfe14c2f7797fbb7f54ef439/transformed/output/jdkImage --disable-plugin system-modules}

* Try:
> Run with --stacktrace option to get the stack trace.
> Run with --info or --debug option to get more log output.
> Run with --scan to get full insights.
> Get more help at https://help.gradle.org.

BUILD FAILED in 43s
Running Gradle task 'assembleDebug'...                             44.1s
Error: Gradle task assembleDebug failed with exit code 1
task: Failed to run task "run:stg:debug": exit status 1

ログを読むとどうも connectivity_plus プラグインで生じたエラーということで、
調べたところズバリなIssueがあり、AGPのバージョンを上げると良いということでしたので、それに従いバージョンアップしました。

https://github.com/fluttercommunity/plus_plugins/issues/3299

--- a/android/settings.gradle
+++ b/android/settings.gradle
@@ -18,7 +18,7 @@ pluginManagement {
 
 plugins {
     id "dev.flutter.flutter-plugin-loader" version "1.0.0"
-    id "com.android.application" version "7.3.0" apply false
+    id "com.android.application" version "8.7.0" apply false
     // START: FlutterFire Configuration
     id "com.google.gms.google-services" version "4.3.15" apply false
     id "com.google.firebase.firebase-perf" version "1.4.1" apply false

その後ビルドを実行すると、以下のようなエラーが出ます。

% task run
task: [run:stg:debug] $FLUTTER_COMMAND run --debug --dart-define-from-file=dart_defines/stg.json
Launching lib/main.dart on Pixel 8a in debug mode...

FAILURE: Build failed with an exception.

* Where:
Build file '/Users/***/***/android/app/build.gradle' line: 2

* What went wrong:
An exception occurred applying plugin request [id: 'com.android.application']
> Failed to apply plugin 'com.android.internal.version-check'.
   > Minimum supported Gradle version is 8.9. Current version is 8.5. If using the gradle wrapper, try editing the distributionUrl in /Users/***/***/android/gradle/wrapper/gradle-wrapper.properties to gradle-8.9-all.zip

* Try:
> Run with --stacktrace option to get the stack trace.
> Run with --info or --debug option to get more log output.
> Run with --scan to get full insights.
> Get more help at https://help.gradle.org.

BUILD FAILED in 8s
Running Gradle task 'assembleDebug'...                              8.7s
Error: Gradle task assembleDebug failed with exit code 1
task: Failed to run task "run:stg:debug": exit status 1

これはAGPが対応しているGradle wrapperバージョンが一致しないというエラーなので、とりあえずやけっぱちで現時点で最新のGradleバージョンを指定しました。たぶんエラーログに出ている 8.9 でもいい。

--- a/android/gradle/wrapper/gradle-wrapper.properties
+++ b/android/gradle/wrapper/gradle-wrapper.properties
@@ -1,5 +1,7 @@
 distributionBase=GRADLE_USER_HOME
 distributionPath=wrapper/dists
+networkTimeout=10000
+validateDistributionUrl=true
 zipStoreBase=GRADLE_USER_HOME
 zipStorePath=wrapper/dists
-distributionUrl=https\://services.gradle.org/distributions/gradle-7.5-all.zip
+distributionUrl=https\://services.gradle.org/distributions/gradle-8.10.2-all.zip

続く。

やったこと③: NDKのバージョンを上げる

実行すると(ry

% task run
task: [run:stg:debug] $FLUTTER_COMMAND run --debug --dart-define-from-file=dart_defines/stg.json
Launching lib/main.dart on Pixel 8a in debug mode...
Your project is configured with Android NDK 23.1.7779620, but the following plugin(s) depend on a different Android NDK version:
- adjust_sdk requires Android NDK 27.0.12077973
- app_badge_plus requires Android NDK 27.0.12077973
- connectivity_plus requires Android NDK 27.0.12077973
- device_info_plus requires Android NDK 27.0.12077973
- firebase_analytics requires Android NDK 27.0.12077973
- firebase_app_installations requires Android NDK 27.0.12077973
- firebase_core requires Android NDK 27.0.12077973
- firebase_crashlytics requires Android NDK 27.0.12077973
- firebase_in_app_messaging requires Android NDK 27.0.12077973
- firebase_messaging requires Android NDK 27.0.12077973
- firebase_performance requires Android NDK 27.0.12077973
- firebase_remote_config requires Android NDK 27.0.12077973
- flutter_image_compress_common requires Android NDK 27.0.12077973
- flutter_plugin_android_lifecycle requires Android NDK 27.0.12077973
- flutter_secure_storage requires Android NDK 27.0.12077973
- image_picker_android requires Android NDK 27.0.12077973
- in_app_review requires Android NDK 27.0.12077973
- package_info_plus requires Android NDK 27.0.12077973
- path_provider_android requires Android NDK 27.0.12077973
- permission_handler_android requires Android NDK 27.0.12077973
- share_plus requires Android NDK 27.0.12077973
- shared_preferences_android requires Android NDK 27.0.12077973
- sqflite_android requires Android NDK 27.0.12077973
- url_launcher_android requires Android NDK 27.0.12077973
- webview_flutter_android requires Android NDK 27.0.12077973
Fix this issue by using the highest Android NDK version (they are backward compatible).
Add the following to /Users/***/***/android/app/build.gradle:

    android {
        ndkVersion = "27.0.12077973"
        ...
    }

見ての通り、アプリのNDKとプラグインのNDKが合ってないというエラーです。言われたとおりに修正します。

--- a/android/app/build.gradle
+++ b/android/app/build.gradle
@@ -57,7 +57,7 @@
 android {
     namespace "com.techouse.driver_app"
     compileSdkVersion flutter.compileSdkVersion
-    ndkVersion flutter.ndkVersion
+    ndkVersion "27.0.12077973" // flutter.ndkVersion
 
     compileOptions {
         sourceCompatibility JavaVersion.VERSION_1_8

やったこと④: build.gradleのファイルコピータスクを捨てるためにflavor対応をする

改めて実行すると(ry

FAILURE: Build failed with an exception.

* What went wrong:
Some problems were found with the configuration of task ':app:generateDebugResources' (type 'ValidateResourcesTask').
  - Gradle detected a problem with the following location: '/Users/***/***/android/app/src/debug/res'.

    Reason: Task ':app:generateDebugResources' uses this output of task ':app:selectGoogleServicesJson' without declaring an explicit or implicit dependency. This can lead to incorrect results being produced, depending on what order the tasks are executed.

    Possible solutions:
      1. Declare task ':app:selectGoogleServicesJson' as an input of ':app:generateDebugResources'.
      2. Declare an explicit dependency on ':app:selectGoogleServicesJson' from ':app:generateDebugResources' using Task#dependsOn.
      3. Declare an explicit dependency on ':app:selectGoogleServicesJson' from ':app:generateDebugResources' using Task#mustRunAfter.

    For more information, please refer to https://docs.gradle.org/8.10.2/userguide/validation_problems.html#implicit_dependency in the Gradle documentation.
  - Gradle detected a problem with the following location: '/Users/***/***/android/app/src/main/res'.

    Reason: Task ':app:generateDebugResources' uses this output of task ':app:selectGoogleServicesJson' without declaring an explicit or implicit dependency. This can lead to incorrect results being produced, depending on what order the tasks are executed.

    Possible solutions:
      1. Declare task ':app:selectGoogleServicesJson' as an input of ':app:generateDebugResources'.
      2. Declare an explicit dependency on ':app:selectGoogleServicesJson' from ':app:generateDebugResources' using Task#dependsOn.
      3. Declare an explicit dependency on ':app:selectGoogleServicesJson' from ':app:generateDebugResources' using Task#mustRunAfter.

    For more information, please refer to https://docs.gradle.org/8.10.2/userguide/validation_problems.html#implicit_dependency in the Gradle documentation.

* Try:
> Run with --stacktrace option to get the stack trace.
> Run with --info or --debug option to get more log output.
> Run with --scan to get full insights.
> Get more help at https://help.gradle.org.

BUILD FAILED in 2s
Running Gradle task 'assembleDebug'...                           2,528ms
Error: Gradle task assembleDebug failed with exit code 1
task: Failed to run task "run:stg:debug": exit status 1

このエラーは、以下の記事のFLAVOR対応をしているとき限定の問題のように思われます。

https://zenn.dev/altiveinc/articles/separating-environments-in-flutter

こちらの記事を参考にしてプロジェクトを構成した場合、selectGoogleServicesJson が既存のGradleタスクとの依存関係を解決できずにエラーになってしまいます。

ただし、この問題は(私が知る限り)ちゃんと直そうと思うと深刻です。というのも、Flutterチームが推奨するFlavor対応をしっかり行う必要が出てくるのですが、既存プロジェクトにそれを入れる場合、構成が変わってしまうのでリスクが高いのです。
また、AndroidだけでなくiOS側も対応する必要があります。悲劇。
私はJDK21対応をやりきるという判断をしたので対応することにしました。

https://docs.flutter.dev/deployment/flavors

ちょっとかじった程度ではあるのですが、 flutter_flavorizr を使うと多少マシにflavor対応できそうです(けっこういろんなことが出来るツールではあるんですが、ミニマルはこんな感じの構成で良さそう)。

https://pub.dev/packages/flutter_flavorizr

まとめ

flavor対応は横着しない。

Discussion