diff --git a/packages/flutter_tools/lib/src/android/gradle_errors.dart b/packages/flutter_tools/lib/src/android/gradle_errors.dart index 81de7798a6..d70335d105 100644 --- a/packages/flutter_tools/lib/src/android/gradle_errors.dart +++ b/packages/flutter_tools/lib/src/android/gradle_errors.dart @@ -72,7 +72,7 @@ final List gradleErrors = [ transformInputIssueHandler, lockFileDepMissingHandler, minCompileSdkVersionHandler, - jvm11RequiredHandler, + incompatibleJavaAndAgpVersionsHandler, outdatedGradleHandler, sslExceptionHandler, zipExceptionHandler, @@ -503,25 +503,38 @@ final GradleHandledError minCompileSdkVersionHandler = GradleHandledError( eventLabel: 'min-compile-sdk-version', ); +final RegExp _agpJavaError = RegExp(r'Android Gradle plugin requires Java (\d+\.?\d*) to run'); + +// If an incompatible Java and Android Gradle Plugin error is caught, +// Android Gradle Plugin throws the required Java version to fix the error. +// Android Gradle Plugin handles the error here: http://shortn/_SgUWyRdywL. + +// If we ever need to reference or check the thrown requirements, +// we can find the Java and Android Gradle Plugin compatability here: +// 'https://developer.android.com/build/releases/past-releases' @visibleForTesting -final GradleHandledError jvm11RequiredHandler = GradleHandledError( +final GradleHandledError incompatibleJavaAndAgpVersionsHandler= GradleHandledError( test: (String line) { - return line.contains('Android Gradle plugin requires Java 11 to run'); + return _agpJavaError.hasMatch(line); }, handler: ({ required String line, required FlutterProject project, required bool usesAndroidX, }) async { + final String helpfulGradleError = line.trim().substring(2); + globals.printBox( - '${globals.logger.terminal.warningMark} You need Java 11 or higher to build your app with this version of Gradle.\n\n' - 'To get Java 11, update to the latest version of Android Studio on https://developer.android.com/studio/install.\n\n' - 'To check the Java version used by Flutter, run `flutter doctor -v`.', + '${globals.logger.terminal.warningMark} $helpfulGradleError\n\n' + 'To fix this issue, try updating to the latest Android SDK and Android Studio on: ${AndroidProject.installAndroidStudioUrl}\n' + 'If that does not work, you can set the Java version used by Flutter by \n' + 'running `flutter config --jdk-dir=““`\n\n' + 'To check the Java version used by Flutter, run `flutter doctor --verbose`', title: _boxTitle, ); return GradleBuildStatus.exit; }, - eventLabel: 'java11-required', + eventLabel: 'incompatible-java-agp-version', ); /// Handles SSL exceptions: https://github.com/flutter/flutter/issues/104628 diff --git a/packages/flutter_tools/lib/src/project.dart b/packages/flutter_tools/lib/src/project.dart index cb3549518a..e998e25944 100644 --- a/packages/flutter_tools/lib/src/project.dart +++ b/packages/flutter_tools/lib/src/project.dart @@ -453,6 +453,11 @@ class AndroidProject extends FlutterProjectPlatform { static const String javaGradleCompatUrl = 'https://docs.gradle.org/current/userguide/compatibility.html#java'; + // User facing link that describes instructions for downloading + // the latest version of Android Studio. + static const String installAndroidStudioUrl = + 'https://developer.android.com/studio/install'; + /// The parent of this project. final FlutterProject parent; diff --git a/packages/flutter_tools/test/general.shard/android/gradle_errors_test.dart b/packages/flutter_tools/test/general.shard/android/gradle_errors_test.dart index 9e5da629c2..3f2fd977a7 100644 --- a/packages/flutter_tools/test/general.shard/android/gradle_errors_test.dart +++ b/packages/flutter_tools/test/general.shard/android/gradle_errors_test.dart @@ -43,7 +43,7 @@ void main() { transformInputIssueHandler, lockFileDepMissingHandler, minCompileSdkVersionHandler, - jvm11RequiredHandler, + incompatibleJavaAndAgpVersionsHandler, outdatedGradleHandler, sslExceptionHandler, zipExceptionHandler, @@ -983,44 +983,40 @@ Execution failed for task ':app:checkDebugAarMetadata'. }); }); - group('Java 11 requirement', () { - testWithoutContext('pattern', () { - expect( - jvm11RequiredHandler.test(''' + group('incompatible java and android gradle plugin versions error', () { + + const String errorMessage = ''' * What went wrong: -A problem occurred evaluating project ':flutter'. -> Failed to apply plugin 'com.android.internal.library'. - > Android Gradle plugin requires Java 11 to run. You are currently using Java 1.8. - You can try some of the following options: +An exception occurred applying plugin request [id: 'com.android.application'] +> Failed to apply plugin 'com.android.internal.application'. + > Android Gradle plugin requires Java 17 to run. You are currently using Java 11. + You can try some of the following options: - changing the IDE settings. - changing the JAVA_HOME environment variable. - - changing `org.gradle.java.home` in `gradle.properties`.''' - ), + - changing `org.gradle.java.home` in `gradle.properties`. +'''; + + testWithoutContext('pattern', () { + expect( + incompatibleJavaAndAgpVersionsHandler.test(errorMessage), isTrue, ); }); testUsingContext('suggestion', () async { - await jvm11RequiredHandler.handler( - project: FakeFlutterProject(), + await incompatibleJavaAndAgpVersionsHandler.handler( + line: errorMessage, + project: FlutterProject.fromDirectoryTest(fileSystem.currentDirectory), usesAndroidX: true, - line: '', ); - expect( - testLogger.statusText, - contains( - '\n' - '┌─ Flutter Fix ─────────────────────────────────────────────────────────────────┐\n' - '│ [!] You need Java 11 or higher to build your app with this version of Gradle. │\n' - '│ │\n' - '│ To get Java 11, update to the latest version of Android Studio on │\n' - '│ https://developer.android.com/studio/install. │\n' - '│ │\n' - '│ To check the Java version used by Flutter, run `flutter doctor -v`. │\n' - '└───────────────────────────────────────────────────────────────────────────────┘\n' - ) - ); + // Ensure the error notes the required Java version, the Java version currently used, + // the android studio and android sdk installation link, the flutter command to set + // the Java version Flutter uses, and the flutter doctor command. + expect(testLogger.statusText, contains('Android Gradle plugin requires Java 17 to run. You are currently using Java 11.')); + expect(testLogger.statusText, contains('https://developer.android.com/studio/install')); + expect(testLogger.statusText, contains('`flutter config --jdk-dir=““`')); + expect(testLogger.statusText, contains('`flutter doctor --verbose`')); }, overrides: { GradleUtils: () => FakeGradleUtils(), Platform: () => fakePlatform('android'),