Unverified Commit 06e2b181 authored by Andrew Kolos's avatar Andrew Kolos Committed by GitHub

[tools] use Java class for all java-searching behavior (#127354)

Fixes #124252, finishing work on the umbrella tracking issue, #126126.

Essentially, after this PR, no (non-test) code should be be referencing/invoking the java home or binary paths.
parent 2bba614a
...@@ -28,8 +28,8 @@ SPEC CHECKSUMS: ...@@ -28,8 +28,8 @@ SPEC CHECKSUMS:
connectivity_macos: 5dae6ee11d320fac7c05f0d08bd08fc32b5514d9 connectivity_macos: 5dae6ee11d320fac7c05f0d08bd08fc32b5514d9
FlutterMacOS: 8f6f14fa908a6fb3fba0cd85dbd81ec4b251fb24 FlutterMacOS: 8f6f14fa908a6fb3fba0cd85dbd81ec4b251fb24
Reachability: 33e18b67625424e47b6cde6d202dce689ad7af96 Reachability: 33e18b67625424e47b6cde6d202dce689ad7af96
url_launcher_macos: 597e05b8e514239626bcf4a850fcf9ef5c856ec3 url_launcher_macos: 5335912b679c073563f29d89d33d10d459f95451
PODFILE CHECKSUM: 2e6060c123c393d6beb3ee5b7beaf789de4d2e47 PODFILE CHECKSUM: 2e6060c123c393d6beb3ee5b7beaf789de4d2e47
COCOAPODS: 1.11.3 COCOAPODS: 1.12.0
...@@ -38,7 +38,6 @@ class AndroidSdk { ...@@ -38,7 +38,6 @@ class AndroidSdk {
reinitialize(); reinitialize();
} }
static const String javaHomeEnvironmentVariable = 'JAVA_HOME';
/// The Android SDK root directory. /// The Android SDK root directory.
final Directory directory; final Directory directory;
......
...@@ -28,18 +28,6 @@ import 'android_studio_validator.dart'; ...@@ -28,18 +28,6 @@ import 'android_studio_validator.dart';
final RegExp _dotHomeStudioVersionMatcher = final RegExp _dotHomeStudioVersionMatcher =
RegExp(r'^\.?(AndroidStudio[^\d]*)([\d.]+)'); RegExp(r'^\.?(AndroidStudio[^\d]*)([\d.]+)');
// TODO(andrewkolos): this global variable is used in several places to provide
// a java binary to multiple Java-dependent tools, including the Android SDK
// and Gradle. If this is null, these tools will implicitly fall back to current
// JAVA_HOME env variable and then to any java found on PATH.
//
// This logic is consistent with that used by flutter doctor to find a valid JDK,
// but this consistency is fragile--the implementations of this logic
// exist independently of each other.
//
// See https://github.com/flutter/flutter/issues/124252.
String? get javaPath => globals.androidStudio?.javaPath;
class AndroidStudio { class AndroidStudio {
/// A [version] value of null represents an unknown version. /// A [version] value of null represents an unknown version.
AndroidStudio( AndroidStudio(
...@@ -173,6 +161,9 @@ class AndroidStudio { ...@@ -173,6 +161,9 @@ class AndroidStudio {
/// The path of the JDK bundled with Android Studio. /// The path of the JDK bundled with Android Studio.
/// ///
/// This will be null if the bundled JDK could not be found or run. /// This will be null if the bundled JDK could not be found or run.
///
/// If you looking to invoke the java binary or add it to the system
/// environment variables, consider using the [Java] class instead.
String? get javaPath => _javaPath; String? get javaPath => _javaPath;
bool get isValid => _isValid; bool get isValid => _isValid;
......
...@@ -75,84 +75,58 @@ class AndroidWorkflow implements Workflow { ...@@ -75,84 +75,58 @@ class AndroidWorkflow implements Workflow {
/// Android Studio. /// Android Studio.
class AndroidValidator extends DoctorValidator { class AndroidValidator extends DoctorValidator {
AndroidValidator({ AndroidValidator({
required Java? java,
required AndroidSdk? androidSdk, required AndroidSdk? androidSdk,
required AndroidStudio? androidStudio,
required FileSystem fileSystem,
required Logger logger, required Logger logger,
required Platform platform, required Platform platform,
required ProcessManager processManager,
required UserMessages userMessages, required UserMessages userMessages,
}) : _androidSdk = androidSdk, }) : _java = java,
_androidStudio = androidStudio, _androidSdk = androidSdk,
_fileSystem = fileSystem,
_logger = logger, _logger = logger,
_platform = platform, _platform = platform,
_processManager = processManager,
_userMessages = userMessages, _userMessages = userMessages,
super('Android toolchain - develop for Android devices'); super('Android toolchain - develop for Android devices');
final Java? _java;
final AndroidSdk? _androidSdk; final AndroidSdk? _androidSdk;
final AndroidStudio? _androidStudio;
final FileSystem _fileSystem;
final Logger _logger; final Logger _logger;
final Platform _platform; final Platform _platform;
final ProcessManager _processManager;
final UserMessages _userMessages; final UserMessages _userMessages;
@override @override
String get slowWarning => '${_task ?? 'This'} is taking a long time...'; String get slowWarning => '${_task ?? 'This'} is taking a long time...';
String? _task; String? _task;
/// Finds the semantic version anywhere in a text.
static final RegExp _javaVersionPattern = RegExp(r'(\d+)(\.(\d+)(\.(\d+))?)?');
/// `java -version` response is not only a number, but also includes other
/// information eg. `openjdk version "1.7.0_212"`.
/// This method extracts only the semantic version from that response.
static String? _extractJavaVersion(String? text) {
if (text == null || text.isEmpty) {
return null;
}
final Match? match = _javaVersionPattern.firstMatch(text);
if (match == null) {
return null;
}
return text.substring(match.start, match.end);
}
/// Returns false if we cannot determine the Java version or if the version /// Returns false if we cannot determine the Java version or if the version
/// is older that the minimum allowed version of 1.8. /// is older that the minimum allowed version of 1.8.
Future<bool> _checkJavaVersion(String javaBinary, List<ValidationMessage> messages) async { Future<bool> _checkJavaVersion(List<ValidationMessage> messages) async {
_task = 'Checking Java status'; _task = 'Checking Java status';
try { try {
if (!_processManager.canRun(javaBinary)) { if (_java?.binaryPath == null) {
messages.add(ValidationMessage.error(_userMessages.androidCantRunJavaBinary(javaBinary))); messages.add(ValidationMessage.error(_userMessages.androidMissingJdk));
return false; return false;
} }
String? javaVersionText; messages.add(ValidationMessage(_userMessages.androidJdkLocation(_java!.binaryPath)));
try { if (!_java!.canRun()) {
// TODO(andrewkolos): Use Java class to find version instead of using duplicate messages.add(ValidationMessage.error(_userMessages.androidCantRunJavaBinary(_java!.binaryPath)));
// code. See https://github.com/flutter/flutter/issues/124252. return false;
_logger.printTrace('java -version');
final ProcessResult result = await _processManager.run(<String>[javaBinary, '-version']);
if (result.exitCode == 0) {
final List<String> versionLines = (result.stderr as String).split('\n');
javaVersionText = versionLines.length >= 2 ? versionLines[1] : versionLines[0];
} }
Version? javaVersion;
try {
javaVersion = _java!.version;
} on Exception catch (error) { } on Exception catch (error) {
_logger.printTrace(error.toString()); _logger.printTrace(error.toString());
} }
final Version? javaVersion = Version.parse(_extractJavaVersion(javaVersionText)); if (javaVersion == null) {
if (javaVersionText == null || javaVersionText.isEmpty || javaVersion == null) {
// Could not determine the java version. // Could not determine the java version.
messages.add(ValidationMessage.error(_userMessages.androidUnknownJavaVersion)); messages.add(ValidationMessage.error(_userMessages.androidUnknownJavaVersion));
return false; return false;
} }
if (javaVersion < kAndroidJavaMinVersion) { if (javaVersion < kAndroidJavaMinVersion) {
messages.add(ValidationMessage.error(_userMessages.androidJavaMinimumVersion(javaVersionText))); messages.add(ValidationMessage.error(_userMessages.androidJavaMinimumVersion(javaVersion.toString())));
return false; return false;
} }
messages.add(ValidationMessage(_userMessages.androidJavaVersion(javaVersionText))); messages.add(ValidationMessage(_userMessages.androidJavaVersion(javaVersion.toString())));
return true; return true;
} finally { } finally {
_task = null; _task = null;
...@@ -234,22 +208,9 @@ class AndroidValidator extends DoctorValidator { ...@@ -234,22 +208,9 @@ class AndroidValidator extends DoctorValidator {
} }
_task = 'Finding Java binary'; _task = 'Finding Java binary';
// Now check for the JDK.
final String? javaBinary = Java.find(
logger: _logger,
androidStudio: _androidStudio,
fileSystem: _fileSystem,
platform: _platform,
processManager: _processManager,
)?.binaryPath;
if (javaBinary == null) {
messages.add(ValidationMessage.error(_userMessages.androidMissingJdk));
return ValidationResult(ValidationType.partial, messages, statusInfo: sdkVersionText);
}
messages.add(ValidationMessage(_userMessages.androidJdkLocation(javaBinary)));
// Check JDK version. // Check JDK version.
if (!await _checkJavaVersion(javaBinary, messages)) { if (!await _checkJavaVersion(messages)) {
return ValidationResult(ValidationType.partial, messages, statusInfo: sdkVersionText); return ValidationResult(ValidationType.partial, messages, statusInfo: sdkVersionText);
} }
......
...@@ -30,10 +30,10 @@ import '../globals.dart' as globals; ...@@ -30,10 +30,10 @@ import '../globals.dart' as globals;
import '../project.dart'; import '../project.dart';
import '../reporting/reporting.dart'; import '../reporting/reporting.dart';
import 'android_builder.dart'; import 'android_builder.dart';
import 'android_sdk.dart';
import 'android_studio.dart'; import 'android_studio.dart';
import 'gradle_errors.dart'; import 'gradle_errors.dart';
import 'gradle_utils.dart'; import 'gradle_utils.dart';
import 'java.dart';
import 'migrations/android_studio_java_gradle_conflict_migration.dart'; import 'migrations/android_studio_java_gradle_conflict_migration.dart';
import 'migrations/top_level_gradle_build_file_migration.dart'; import 'migrations/top_level_gradle_build_file_migration.dart';
import 'multidex.dart'; import 'multidex.dart';
...@@ -132,6 +132,7 @@ const Duration kMaxRetryTime = Duration(seconds: 10); ...@@ -132,6 +132,7 @@ const Duration kMaxRetryTime = Duration(seconds: 10);
/// An implementation of the [AndroidBuilder] that delegates to gradle. /// An implementation of the [AndroidBuilder] that delegates to gradle.
class AndroidGradleBuilder implements AndroidBuilder { class AndroidGradleBuilder implements AndroidBuilder {
AndroidGradleBuilder({ AndroidGradleBuilder({
required Java? java,
required Logger logger, required Logger logger,
required ProcessManager processManager, required ProcessManager processManager,
required FileSystem fileSystem, required FileSystem fileSystem,
...@@ -140,7 +141,8 @@ class AndroidGradleBuilder implements AndroidBuilder { ...@@ -140,7 +141,8 @@ class AndroidGradleBuilder implements AndroidBuilder {
required GradleUtils gradleUtils, required GradleUtils gradleUtils,
required Platform platform, required Platform platform,
required AndroidStudio? androidStudio, required AndroidStudio? androidStudio,
}) : _logger = logger, }) : _java = java,
_logger = logger,
_fileSystem = fileSystem, _fileSystem = fileSystem,
_artifacts = artifacts, _artifacts = artifacts,
_usage = usage, _usage = usage,
...@@ -149,6 +151,7 @@ class AndroidGradleBuilder implements AndroidBuilder { ...@@ -149,6 +151,7 @@ class AndroidGradleBuilder implements AndroidBuilder {
_fileSystemUtils = FileSystemUtils(fileSystem: fileSystem, platform: platform), _fileSystemUtils = FileSystemUtils(fileSystem: fileSystem, platform: platform),
_processUtils = ProcessUtils(logger: logger, processManager: processManager); _processUtils = ProcessUtils(logger: logger, processManager: processManager);
final Java? _java;
final Logger _logger; final Logger _logger;
final ProcessUtils _processUtils; final ProcessUtils _processUtils;
final FileSystem _fileSystem; final FileSystem _fileSystem;
...@@ -422,15 +425,11 @@ class AndroidGradleBuilder implements AndroidBuilder { ...@@ -422,15 +425,11 @@ class AndroidGradleBuilder implements AndroidBuilder {
..start(); ..start();
int exitCode = 1; int exitCode = 1;
try { try {
final String? javaHome = globals.java?.javaHome;
exitCode = await _processUtils.stream( exitCode = await _processUtils.stream(
command, command,
workingDirectory: project.android.hostAppGradleRoot.path, workingDirectory: project.android.hostAppGradleRoot.path,
allowReentrantFlutter: true, allowReentrantFlutter: true,
environment: <String, String>{ environment: _java?.environment,
if (javaHome != null)
AndroidSdk.javaHomeEnvironmentVariable: javaHome,
},
mapFunction: consumeLog, mapFunction: consumeLog,
); );
} on ProcessException catch (exception) { } on ProcessException catch (exception) {
...@@ -692,15 +691,11 @@ class AndroidGradleBuilder implements AndroidBuilder { ...@@ -692,15 +691,11 @@ class AndroidGradleBuilder implements AndroidBuilder {
..start(); ..start();
RunResult result; RunResult result;
try { try {
final String? javaHome = globals.java?.javaHome;
result = await _processUtils.run( result = await _processUtils.run(
command, command,
workingDirectory: project.android.hostAppGradleRoot.path, workingDirectory: project.android.hostAppGradleRoot.path,
allowReentrantFlutter: true, allowReentrantFlutter: true,
environment: <String, String>{ environment: _java?.environment,
if (javaHome != null)
AndroidSdk.javaHomeEnvironmentVariable: javaHome,
},
); );
} finally { } finally {
status.stop(); status.stop();
...@@ -745,15 +740,11 @@ class AndroidGradleBuilder implements AndroidBuilder { ...@@ -745,15 +740,11 @@ class AndroidGradleBuilder implements AndroidBuilder {
..start(); ..start();
RunResult result; RunResult result;
try { try {
final String? javaHome = globals.java?.javaHome;
result = await _processUtils.run( result = await _processUtils.run(
command, command,
workingDirectory: project.android.hostAppGradleRoot.path, workingDirectory: project.android.hostAppGradleRoot.path,
allowReentrantFlutter: true, allowReentrantFlutter: true,
environment: <String, String>{ environment: _java?.environment,
if (javaHome != null)
AndroidSdk.javaHomeEnvironmentVariable: javaHome,
},
); );
} finally { } finally {
status.stop(); status.stop();
......
...@@ -11,8 +11,6 @@ import '../base/terminal.dart'; ...@@ -11,8 +11,6 @@ import '../base/terminal.dart';
import '../globals.dart' as globals; import '../globals.dart' as globals;
import '../project.dart'; import '../project.dart';
import '../reporting/reporting.dart'; import '../reporting/reporting.dart';
import 'android_sdk.dart';
import 'android_studio.dart';
import 'gradle_utils.dart'; import 'gradle_utils.dart';
import 'multidex.dart'; import 'multidex.dart';
...@@ -379,10 +377,7 @@ final GradleHandledError flavorUndefinedHandler = GradleHandledError( ...@@ -379,10 +377,7 @@ final GradleHandledError flavorUndefinedHandler = GradleHandledError(
], ],
throwOnError: true, throwOnError: true,
workingDirectory: project.android.hostAppGradleRoot.path, workingDirectory: project.android.hostAppGradleRoot.path,
environment: <String, String>{ environment: globals.java?.environment,
if (javaPath != null)
AndroidSdk.javaHomeEnvironmentVariable: javaPath!,
},
); );
// Extract build types and product flavors. // Extract build types and product flavors.
final Set<String> variants = <String>{}; final Set<String> variants = <String>{};
......
...@@ -9,13 +9,14 @@ import '../base/logger.dart'; ...@@ -9,13 +9,14 @@ import '../base/logger.dart';
import '../base/os.dart'; import '../base/os.dart';
import '../base/platform.dart'; import '../base/platform.dart';
import '../base/process.dart'; import '../base/process.dart';
import '../base/version.dart';
import 'android_studio.dart'; import 'android_studio.dart';
const String _javaHomeEnvironmentVariable = 'JAVA_HOME'; const String _javaExecutable = 'java';
const String _kJavaExecutable = 'java';
/// Represents an installation of Java. /// Represents an installation of Java.
class Java { class Java {
Java({ Java({
required this.javaHome, required this.javaHome,
required this.binaryPath, required this.binaryPath,
...@@ -31,6 +32,15 @@ class Java { ...@@ -31,6 +32,15 @@ class Java {
_processManager = processManager, _processManager = processManager,
_processUtils = ProcessUtils(processManager: processManager, logger: logger); _processUtils = ProcessUtils(processManager: processManager, logger: logger);
/// Within the Java ecosystem, this environment variable is typically set
/// the install location of a Java Runtime Environment (JRE) or Java
/// Development Kit (JDK).
///
/// Tools that depend on Java and need to find it will often check this
/// variable. If you are looking to set `JAVA_HOME` when stating a process,
/// consider using the [environment] instance property instead.
static String javaHomeEnvironmentVariable = 'JAVA_HOME';
/// Finds the Java runtime environment that should be used for all java-dependent /// Finds the Java runtime environment that should be used for all java-dependent
/// operations across the tool. /// operations across the tool.
/// ///
...@@ -41,13 +51,6 @@ class Java { ...@@ -41,13 +51,6 @@ class Java {
/// 3. the java binary found on PATH. /// 3. the java binary found on PATH.
/// ///
/// Returns null if no java binary could be found. /// Returns null if no java binary could be found.
// TODO(andrewkolos): To prevent confusion when debugging Android-related
// issues (see https://github.com/flutter/flutter/issues/122609 for an example),
// this logic should be consistently followed by any Java-dependent operation
// across the the tool (building Android apps, interacting with the Android SDK, etc.).
// Currently, this consistency is fragile since the logic used for building
// Android apps exists independently of this method.
// See https://github.com/flutter/flutter/issues/124252.
static Java? find({ static Java? find({
required AndroidStudio? androidStudio, required AndroidStudio? androidStudio,
required Logger logger, required Logger logger,
...@@ -89,7 +92,7 @@ class Java { ...@@ -89,7 +92,7 @@ class Java {
); );
} }
/// The path of the runtime's home directory. /// The path of the runtime environments' home directory.
/// ///
/// This should only be used for logging and validation purposes. /// This should only be used for logging and validation purposes.
/// If you need to set JAVA_HOME when starting a process, consider /// If you need to set JAVA_HOME when starting a process, consider
...@@ -98,7 +101,7 @@ class Java { ...@@ -98,7 +101,7 @@ class Java {
/// a new method to this class instead. /// a new method to this class instead.
final String? javaHome; final String? javaHome;
/// The path of the runtime's java binary. /// The path of the runtime environments' java binary.
/// ///
/// This should be only used for logging and validation purposes. /// This should be only used for logging and validation purposes.
/// If you need to invoke the binary directly, consider adding a new method /// If you need to invoke the binary directly, consider adding a new method
...@@ -120,7 +123,7 @@ class Java { ...@@ -120,7 +123,7 @@ class Java {
/// processes, such as Gradle or Android SDK tools (avdmanager, sdkmanager, etc.) /// processes, such as Gradle or Android SDK tools (avdmanager, sdkmanager, etc.)
Map<String, String> get environment { Map<String, String> get environment {
return <String, String>{ return <String, String>{
if (javaHome != null) _javaHomeEnvironmentVariable: javaHome!, if (javaHome != null) javaHomeEnvironmentVariable: javaHome!,
'PATH': _fileSystem.path.dirname(binaryPath) + 'PATH': _fileSystem.path.dirname(binaryPath) +
_os.pathVarSeparator + _os.pathVarSeparator +
_platform.environment['PATH']!, _platform.environment['PATH']!,
...@@ -129,7 +132,7 @@ class Java { ...@@ -129,7 +132,7 @@ class Java {
/// Returns the version of java in the format \d(.\d)+(.\d)+ /// Returns the version of java in the format \d(.\d)+(.\d)+
/// Returns null if version could not be determined. /// Returns null if version could not be determined.
late final JavaVersion? version = (() { late final Version? version = (() {
final RunResult result = _processUtils.runSync( final RunResult result = _processUtils.runSync(
<String>[binaryPath, '--version'], <String>[binaryPath, '--version'],
environment: environment, environment: environment,
...@@ -138,7 +141,38 @@ class Java { ...@@ -138,7 +141,38 @@ class Java {
_logger.printTrace('java --version failed: exitCode: ${result.exitCode}' _logger.printTrace('java --version failed: exitCode: ${result.exitCode}'
' stdout: ${result.stdout} stderr: ${result.stderr}'); ' stdout: ${result.stdout} stderr: ${result.stderr}');
} }
return JavaVersion.tryParseFromJavaOutput(result.stdout, logger: _logger); final String rawVersionOutput = result.stdout;
final List<String> versionLines = rawVersionOutput.split('\n');
// Should look something like 'openjdk 19.0.2 2023-01-17'.
final String longVersionText = versionLines.length >= 2 ? versionLines[1] : versionLines[0];
// The contents that matter come in the format '11.0.18' or '1.8.0_202'.
final RegExp jdkVersionRegex = RegExp(r'\d+\.\d+(\.\d+(?:_\d+)?)?');
final Iterable<RegExpMatch> matches =
jdkVersionRegex.allMatches(rawVersionOutput);
if (matches.isEmpty) {
_logger.printWarning(_formatJavaVersionWarning(rawVersionOutput));
return null;
}
final String? version = matches.first.group(0);
if (version == null || version.split('_').isEmpty) {
_logger.printWarning(_formatJavaVersionWarning(rawVersionOutput));
return null;
}
// Trim away _d+ from versions 1.8 and below.
final String versionWithoutBuildInfo = version.split('_').first;
final Version? parsedVersion = Version.parse(versionWithoutBuildInfo);
if (parsedVersion == null) {
return null;
}
return Version.withText(
parsedVersion.major,
parsedVersion.minor,
parsedVersion.patch,
longVersionText,
);
})(); })();
bool canRun() { bool canRun() {
...@@ -156,7 +190,7 @@ String? _findJavaHome({ ...@@ -156,7 +190,7 @@ String? _findJavaHome({
return androidStudioJavaPath; return androidStudioJavaPath;
} }
final String? javaHomeEnv = platform.environment[_javaHomeEnvironmentVariable]; final String? javaHomeEnv = platform.environment[Java.javaHomeEnvironmentVariable];
if (javaHomeEnv != null) { if (javaHomeEnv != null) {
return javaHomeEnv; return javaHomeEnv;
} }
...@@ -175,7 +209,7 @@ String? _findJavaBinary({ ...@@ -175,7 +209,7 @@ String? _findJavaBinary({
} }
// Fallback to PATH based lookup. // Fallback to PATH based lookup.
return operatingSystemUtils.which(_kJavaExecutable)?.path; return operatingSystemUtils.which(_javaExecutable)?.path;
} }
// Returns a user visible String that says the tool failed to parse // Returns a user visible String that says the tool failed to parse
...@@ -187,44 +221,3 @@ String _formatJavaVersionWarning(String javaVersionRaw) { ...@@ -187,44 +221,3 @@ String _formatJavaVersionWarning(String javaVersionRaw) {
'https://github.com/flutter/flutter/issues/ ' 'https://github.com/flutter/flutter/issues/ '
'and if one does not exist file a new issue.'; 'and if one does not exist file a new issue.';
} }
class JavaVersion {
JavaVersion({
required this.longText,
required this.number
});
/// Typically the first line of the output from `java --version`.
/// For example, `"openjdk 19.0.2 2023-01-17"`.
final String longText;
/// The version number. For example, `"19.0.2."`.
final String number;
/// Extracts JDK version from the output of java --version.
static JavaVersion? tryParseFromJavaOutput(String rawVersionOutput, {
required Logger logger,
}) {
final List<String> versionLines = rawVersionOutput.split('\n');
final String longText = versionLines.length >= 2 ? versionLines[1] : versionLines[0];
// The contents that matter come in the format '11.0.18' or '1.8.0_202'.
final RegExp jdkVersionRegex = RegExp(r'\d+\.\d+(\.\d+(?:_\d+)?)?');
final Iterable<RegExpMatch> matches =
jdkVersionRegex.allMatches(rawVersionOutput);
if (matches.isEmpty) {
logger.printWarning(_formatJavaVersionWarning(rawVersionOutput));
return null;
}
final String? rawShortText = matches.first.group(0);
if (rawShortText == null || rawShortText.split('_').isEmpty) {
logger.printWarning(_formatJavaVersionWarning(rawVersionOutput));
return null;
}
// Trim away _d+ from versions 1.8 and below.
final String shortText = rawShortText.split('_').first;
return JavaVersion(longText: longText, number: shortText);
}
}
...@@ -99,14 +99,12 @@ class AndroidStudioJavaGradleConflictMigration extends ProjectMigrator { ...@@ -99,14 +99,12 @@ class AndroidStudioJavaGradleConflictMigration extends ProjectMigrator {
return; return;
} }
final String? javaVersionString = _java?.version?.number; if (_java?.version == null) {
final Version? javaVersion = Version.parse(javaVersionString);
if (javaVersion == null) {
logger.printTrace(javaVersionNotFound); logger.printTrace(javaVersionNotFound);
return; return;
} }
if (javaVersion.major != flamingoBundledJava.major) { if (_java!.version!.major != flamingoBundledJava.major) {
logger.printTrace(javaVersionNot17); logger.printTrace(javaVersionNot17);
return; return;
} }
......
...@@ -88,6 +88,7 @@ Future<T> runInContext<T>( ...@@ -88,6 +88,7 @@ Future<T> runInContext<T>(
overrides: overrides, overrides: overrides,
fallbacks: <Type, Generator>{ fallbacks: <Type, Generator>{
AndroidBuilder: () => AndroidGradleBuilder( AndroidBuilder: () => AndroidGradleBuilder(
java: globals.java,
logger: globals.logger, logger: globals.logger,
processManager: globals.processManager, processManager: globals.processManager,
fileSystem: globals.fs, fileSystem: globals.fs,
...@@ -111,12 +112,10 @@ Future<T> runInContext<T>( ...@@ -111,12 +112,10 @@ Future<T> runInContext<T>(
AndroidSdk: AndroidSdk.locateAndroidSdk, AndroidSdk: AndroidSdk.locateAndroidSdk,
AndroidStudio: AndroidStudio.latestValid, AndroidStudio: AndroidStudio.latestValid,
AndroidValidator: () => AndroidValidator( AndroidValidator: () => AndroidValidator(
androidStudio: globals.androidStudio, java: globals.java,
androidSdk: globals.androidSdk, androidSdk: globals.androidSdk,
fileSystem: globals.fs,
logger: globals.logger, logger: globals.logger,
platform: globals.platform, platform: globals.platform,
processManager: globals.processManager,
userMessages: globals.userMessages, userMessages: globals.userMessages,
), ),
AndroidWorkflow: () => AndroidWorkflow( AndroidWorkflow: () => AndroidWorkflow(
......
...@@ -7,8 +7,7 @@ import 'dart:async'; ...@@ -7,8 +7,7 @@ import 'dart:async';
import 'package:meta/meta.dart'; import 'package:meta/meta.dart';
import 'package:package_config/package_config.dart'; import 'package:package_config/package_config.dart';
import 'android/android_sdk.dart'; import 'android/java.dart';
import 'android/android_studio.dart';
import 'base/common.dart'; import 'base/common.dart';
import 'base/error_handling_io.dart'; import 'base/error_handling_io.dart';
import 'base/file_system.dart'; import 'base/file_system.dart';
...@@ -387,12 +386,17 @@ class AndroidGenSnapshotArtifacts extends EngineCachedArtifact { ...@@ -387,12 +386,17 @@ class AndroidGenSnapshotArtifacts extends EngineCachedArtifact {
/// A cached artifact containing the Maven dependencies used to build Android projects. /// A cached artifact containing the Maven dependencies used to build Android projects.
/// ///
/// This is a no-op if the android SDK is not available. /// This is a no-op if the android SDK is not available.
///
/// Set [Java] to `null` to indicate that no Java/JDK installation could be found.
class AndroidMavenArtifacts extends ArtifactSet { class AndroidMavenArtifacts extends ArtifactSet {
AndroidMavenArtifacts(this.cache, { AndroidMavenArtifacts(this.cache, {
required Java? java,
required Platform platform, required Platform platform,
}) : _platform = platform, }) : _java = java,
_platform = platform,
super(DevelopmentArtifact.androidMaven); super(DevelopmentArtifact.androidMaven);
final Java? _java;
final Platform _platform; final Platform _platform;
final Cache cache; final Cache cache;
...@@ -404,6 +408,8 @@ class AndroidMavenArtifacts extends ArtifactSet { ...@@ -404,6 +408,8 @@ class AndroidMavenArtifacts extends ArtifactSet {
OperatingSystemUtils operatingSystemUtils, OperatingSystemUtils operatingSystemUtils,
{bool offline = false} {bool offline = false}
) async { ) async {
// TODO(andrewkolos): Should this really be no-op if the Android SDK
// is unavailable? https://github.com/flutter/flutter/issues/127848
if (globals.androidSdk == null) { if (globals.androidSdk == null) {
return; return;
} }
...@@ -424,10 +430,7 @@ class AndroidMavenArtifacts extends ArtifactSet { ...@@ -424,10 +430,7 @@ class AndroidMavenArtifacts extends ArtifactSet {
'--project-cache-dir', tempDir.path, '--project-cache-dir', tempDir.path,
'resolveDependencies', 'resolveDependencies',
], ],
environment: <String, String>{ environment: _java?.environment,
if (javaPath != null)
AndroidSdk.javaHomeEnvironmentVariable: javaPath!,
},
); );
if (processResult.exitCode != 0) { if (processResult.exitCode != 0) {
logger.printError('Failed to download the Android dependencies'); logger.printError('Failed to download the Android dependencies');
......
...@@ -14,6 +14,7 @@ import 'base/error_handling_io.dart'; ...@@ -14,6 +14,7 @@ import 'base/error_handling_io.dart';
import 'base/file_system.dart'; import 'base/file_system.dart';
import 'base/logger.dart'; import 'base/logger.dart';
import 'base/utils.dart'; import 'base/utils.dart';
import 'base/version.dart';
import 'bundle.dart' as bundle; import 'bundle.dart' as bundle;
import 'cmake_project.dart'; import 'cmake_project.dart';
import 'features.dart'; import 'features.dart';
...@@ -568,7 +569,7 @@ class AndroidProject extends FlutterProjectPlatform { ...@@ -568,7 +569,7 @@ class AndroidProject extends FlutterProjectPlatform {
hostAppGradleRoot, globals.logger, globals.processManager); hostAppGradleRoot, globals.logger, globals.processManager);
final String? agpVersion = final String? agpVersion =
gradle.getAgpVersion(hostAppGradleRoot, globals.logger); gradle.getAgpVersion(hostAppGradleRoot, globals.logger);
final String? javaVersion = globals.java?.version?.number; final String? javaVersion = _versionToParsableString(globals.java?.version);
// Assume valid configuration. // Assume valid configuration.
String description = validJavaGradleAgpString; String description = validJavaGradleAgpString;
...@@ -893,3 +894,12 @@ class CompatibilityResult { ...@@ -893,3 +894,12 @@ class CompatibilityResult {
final bool success; final bool success;
final String description; final String description;
} }
/// Converts a [Version] to a string that can be parsed by [Version.parse].
String? _versionToParsableString(Version? version) {
if (version == null) {
return null;
}
return '${version.major}.${version.minor}.${version.patch}';
}
...@@ -46,6 +46,7 @@ void main() { ...@@ -46,6 +46,7 @@ void main() {
testUsingContext('Can immediately tool exit on recognized exit code/stderr', () async { testUsingContext('Can immediately tool exit on recognized exit code/stderr', () async {
final AndroidGradleBuilder builder = AndroidGradleBuilder( final AndroidGradleBuilder builder = AndroidGradleBuilder(
java: FakeJava(),
logger: logger, logger: logger,
processManager: processManager, processManager: processManager,
fileSystem: fileSystem, fileSystem: fileSystem,
...@@ -138,6 +139,7 @@ void main() { ...@@ -138,6 +139,7 @@ void main() {
testUsingContext('Verbose mode for APKs includes Gradle stacktrace and sets debug log level', () async { testUsingContext('Verbose mode for APKs includes Gradle stacktrace and sets debug log level', () async {
final AndroidGradleBuilder builder = AndroidGradleBuilder( final AndroidGradleBuilder builder = AndroidGradleBuilder(
java: FakeJava(),
logger: BufferLogger.test(verbose: true), logger: BufferLogger.test(verbose: true),
processManager: processManager, processManager: processManager,
fileSystem: fileSystem, fileSystem: fileSystem,
...@@ -205,6 +207,7 @@ void main() { ...@@ -205,6 +207,7 @@ void main() {
testUsingContext('Can retry build on recognized exit code/stderr', () async { testUsingContext('Can retry build on recognized exit code/stderr', () async {
final AndroidGradleBuilder builder = AndroidGradleBuilder( final AndroidGradleBuilder builder = AndroidGradleBuilder(
java: FakeJava(),
logger: logger, logger: logger,
processManager: processManager, processManager: processManager,
fileSystem: fileSystem, fileSystem: fileSystem,
...@@ -310,6 +313,7 @@ void main() { ...@@ -310,6 +313,7 @@ void main() {
testUsingContext('Converts recognized ProcessExceptions into tools exits', () async { testUsingContext('Converts recognized ProcessExceptions into tools exits', () async {
final AndroidGradleBuilder builder = AndroidGradleBuilder( final AndroidGradleBuilder builder = AndroidGradleBuilder(
java: FakeJava(),
logger: logger, logger: logger,
processManager: processManager, processManager: processManager,
fileSystem: fileSystem, fileSystem: fileSystem,
...@@ -402,6 +406,7 @@ void main() { ...@@ -402,6 +406,7 @@ void main() {
testUsingContext('rethrows unrecognized ProcessException', () async { testUsingContext('rethrows unrecognized ProcessException', () async {
final AndroidGradleBuilder builder = AndroidGradleBuilder( final AndroidGradleBuilder builder = AndroidGradleBuilder(
java: FakeJava(),
logger: logger, logger: logger,
processManager: processManager, processManager: processManager,
fileSystem: fileSystem, fileSystem: fileSystem,
...@@ -466,6 +471,7 @@ void main() { ...@@ -466,6 +471,7 @@ void main() {
testUsingContext('logs success event after a successful retry', () async { testUsingContext('logs success event after a successful retry', () async {
final AndroidGradleBuilder builder = AndroidGradleBuilder( final AndroidGradleBuilder builder = AndroidGradleBuilder(
java: FakeJava(),
logger: logger, logger: logger,
processManager: processManager, processManager: processManager,
fileSystem: fileSystem, fileSystem: fileSystem,
...@@ -569,6 +575,7 @@ void main() { ...@@ -569,6 +575,7 @@ void main() {
testUsingContext('performs code size analysis and sends analytics', () async { testUsingContext('performs code size analysis and sends analytics', () async {
final AndroidGradleBuilder builder = AndroidGradleBuilder( final AndroidGradleBuilder builder = AndroidGradleBuilder(
java: FakeJava(),
logger: logger, logger: logger,
processManager: processManager, processManager: processManager,
fileSystem: fileSystem, fileSystem: fileSystem,
...@@ -670,6 +677,7 @@ void main() { ...@@ -670,6 +677,7 @@ void main() {
testUsingContext('indicates that an APK has been built successfully', () async { testUsingContext('indicates that an APK has been built successfully', () async {
final AndroidGradleBuilder builder = AndroidGradleBuilder( final AndroidGradleBuilder builder = AndroidGradleBuilder(
java: FakeJava(),
logger: logger, logger: logger,
processManager: processManager, processManager: processManager,
fileSystem: fileSystem, fileSystem: fileSystem,
...@@ -797,6 +805,7 @@ android { ...@@ -797,6 +805,7 @@ android {
testUsingContext('can call custom gradle task getBuildOptions and parse the result', () async { testUsingContext('can call custom gradle task getBuildOptions and parse the result', () async {
final AndroidGradleBuilder builder = AndroidGradleBuilder( final AndroidGradleBuilder builder = AndroidGradleBuilder(
java: FakeJava(),
logger: logger, logger: logger,
processManager: processManager, processManager: processManager,
fileSystem: fileSystem, fileSystem: fileSystem,
...@@ -831,6 +840,7 @@ BuildVariant: paidProfile ...@@ -831,6 +840,7 @@ BuildVariant: paidProfile
testUsingContext('getBuildOptions returns empty list if gradle returns error', () async { testUsingContext('getBuildOptions returns empty list if gradle returns error', () async {
final AndroidGradleBuilder builder = AndroidGradleBuilder( final AndroidGradleBuilder builder = AndroidGradleBuilder(
java: FakeJava(),
logger: logger, logger: logger,
processManager: processManager, processManager: processManager,
fileSystem: fileSystem, fileSystem: fileSystem,
...@@ -861,6 +871,7 @@ Gradle Crashed ...@@ -861,6 +871,7 @@ Gradle Crashed
testUsingContext("doesn't indicate how to consume an AAR when printHowToConsumeAar is false", () async { testUsingContext("doesn't indicate how to consume an AAR when printHowToConsumeAar is false", () async {
final AndroidGradleBuilder builder = AndroidGradleBuilder( final AndroidGradleBuilder builder = AndroidGradleBuilder(
java: FakeJava(),
logger: logger, logger: logger,
processManager: processManager, processManager: processManager,
fileSystem: fileSystem, fileSystem: fileSystem,
...@@ -926,6 +937,7 @@ Gradle Crashed ...@@ -926,6 +937,7 @@ Gradle Crashed
testUsingContext('Verbose mode for AARs includes Gradle stacktrace and sets debug log level', () async { testUsingContext('Verbose mode for AARs includes Gradle stacktrace and sets debug log level', () async {
final AndroidGradleBuilder builder = AndroidGradleBuilder( final AndroidGradleBuilder builder = AndroidGradleBuilder(
java: FakeJava(),
logger: BufferLogger.test(verbose: true), logger: BufferLogger.test(verbose: true),
processManager: processManager, processManager: processManager,
fileSystem: fileSystem, fileSystem: fileSystem,
...@@ -984,6 +996,7 @@ Gradle Crashed ...@@ -984,6 +996,7 @@ Gradle Crashed
testUsingContext('gradle exit code and stderr is forwarded to tool exit', () async { testUsingContext('gradle exit code and stderr is forwarded to tool exit', () async {
final AndroidGradleBuilder builder = AndroidGradleBuilder( final AndroidGradleBuilder builder = AndroidGradleBuilder(
java: FakeJava(),
logger: logger, logger: logger,
processManager: processManager, processManager: processManager,
fileSystem: fileSystem, fileSystem: fileSystem,
...@@ -1043,6 +1056,7 @@ Gradle Crashed ...@@ -1043,6 +1056,7 @@ Gradle Crashed
testUsingContext('build apk uses selected local engine with arm32 ABI', () async { testUsingContext('build apk uses selected local engine with arm32 ABI', () async {
final AndroidGradleBuilder builder = AndroidGradleBuilder( final AndroidGradleBuilder builder = AndroidGradleBuilder(
java: FakeJava(),
logger: logger, logger: logger,
processManager: processManager, processManager: processManager,
fileSystem: fileSystem, fileSystem: fileSystem,
...@@ -1121,6 +1135,7 @@ Gradle Crashed ...@@ -1121,6 +1135,7 @@ Gradle Crashed
testUsingContext('build apk uses selected local engine with arm64 ABI', () async { testUsingContext('build apk uses selected local engine with arm64 ABI', () async {
final AndroidGradleBuilder builder = AndroidGradleBuilder( final AndroidGradleBuilder builder = AndroidGradleBuilder(
java: FakeJava(),
logger: logger, logger: logger,
processManager: processManager, processManager: processManager,
fileSystem: fileSystem, fileSystem: fileSystem,
...@@ -1199,6 +1214,7 @@ Gradle Crashed ...@@ -1199,6 +1214,7 @@ Gradle Crashed
testUsingContext('build apk uses selected local engine with x86 ABI', () async { testUsingContext('build apk uses selected local engine with x86 ABI', () async {
final AndroidGradleBuilder builder = AndroidGradleBuilder( final AndroidGradleBuilder builder = AndroidGradleBuilder(
java: FakeJava(),
logger: logger, logger: logger,
processManager: processManager, processManager: processManager,
fileSystem: fileSystem, fileSystem: fileSystem,
...@@ -1277,6 +1293,7 @@ Gradle Crashed ...@@ -1277,6 +1293,7 @@ Gradle Crashed
testUsingContext('build apk uses selected local engine with x64 ABI', () async { testUsingContext('build apk uses selected local engine with x64 ABI', () async {
final AndroidGradleBuilder builder = AndroidGradleBuilder( final AndroidGradleBuilder builder = AndroidGradleBuilder(
java: FakeJava(),
logger: logger, logger: logger,
processManager: processManager, processManager: processManager,
fileSystem: fileSystem, fileSystem: fileSystem,
...@@ -1356,6 +1373,7 @@ Gradle Crashed ...@@ -1356,6 +1373,7 @@ Gradle Crashed
testUsingContext('honors --no-android-gradle-daemon setting', () async { testUsingContext('honors --no-android-gradle-daemon setting', () async {
final AndroidGradleBuilder builder = AndroidGradleBuilder( final AndroidGradleBuilder builder = AndroidGradleBuilder(
java: FakeJava(),
logger: logger, logger: logger,
processManager: processManager, processManager: processManager,
fileSystem: fileSystem, fileSystem: fileSystem,
...@@ -1416,6 +1434,7 @@ Gradle Crashed ...@@ -1416,6 +1434,7 @@ Gradle Crashed
testUsingContext('build aar uses selected local engine with arm32 ABI', () async { testUsingContext('build aar uses selected local engine with arm32 ABI', () async {
final AndroidGradleBuilder builder = AndroidGradleBuilder( final AndroidGradleBuilder builder = AndroidGradleBuilder(
java: FakeJava(),
logger: logger, logger: logger,
processManager: processManager, processManager: processManager,
fileSystem: fileSystem, fileSystem: fileSystem,
...@@ -1503,6 +1522,7 @@ Gradle Crashed ...@@ -1503,6 +1522,7 @@ Gradle Crashed
testUsingContext('build aar uses selected local engine with x64 ABI', () async { testUsingContext('build aar uses selected local engine with x64 ABI', () async {
final AndroidGradleBuilder builder = AndroidGradleBuilder( final AndroidGradleBuilder builder = AndroidGradleBuilder(
java: FakeJava(),
logger: logger, logger: logger,
processManager: processManager, processManager: processManager,
fileSystem: fileSystem, fileSystem: fileSystem,
...@@ -1590,6 +1610,7 @@ Gradle Crashed ...@@ -1590,6 +1610,7 @@ Gradle Crashed
testUsingContext('build aar uses selected local engine with x86 ABI', () async { testUsingContext('build aar uses selected local engine with x86 ABI', () async {
final AndroidGradleBuilder builder = AndroidGradleBuilder( final AndroidGradleBuilder builder = AndroidGradleBuilder(
java: FakeJava(),
logger: logger, logger: logger,
processManager: processManager, processManager: processManager,
fileSystem: fileSystem, fileSystem: fileSystem,
...@@ -1677,6 +1698,7 @@ Gradle Crashed ...@@ -1677,6 +1698,7 @@ Gradle Crashed
testUsingContext('build aar uses selected local engine on x64 ABI', () async { testUsingContext('build aar uses selected local engine on x64 ABI', () async {
final AndroidGradleBuilder builder = AndroidGradleBuilder( final AndroidGradleBuilder builder = AndroidGradleBuilder(
java: FakeJava(),
logger: logger, logger: logger,
processManager: processManager, processManager: processManager,
fileSystem: fileSystem, fileSystem: fileSystem,
...@@ -1773,5 +1795,5 @@ class FakeGradleUtils extends Fake implements GradleUtils { ...@@ -1773,5 +1795,5 @@ class FakeGradleUtils extends Fake implements GradleUtils {
class FakeAndroidStudio extends Fake implements AndroidStudio { class FakeAndroidStudio extends Fake implements AndroidStudio {
@override @override
String get javaPath => 'java'; String get javaPath => '/android-studio/jbr';
} }
...@@ -6,7 +6,6 @@ import 'package:file/file.dart'; ...@@ -6,7 +6,6 @@ import 'package:file/file.dart';
import 'package:file/memory.dart'; import 'package:file/memory.dart';
import 'package:flutter_tools/src/android/android_studio.dart'; import 'package:flutter_tools/src/android/android_studio.dart';
import 'package:flutter_tools/src/android/gradle_utils.dart'; import 'package:flutter_tools/src/android/gradle_utils.dart';
import 'package:flutter_tools/src/android/java.dart';
import 'package:flutter_tools/src/android/migrations/android_studio_java_gradle_conflict_migration.dart'; import 'package:flutter_tools/src/android/migrations/android_studio_java_gradle_conflict_migration.dart';
import 'package:flutter_tools/src/android/migrations/top_level_gradle_build_file_migration.dart'; import 'package:flutter_tools/src/android/migrations/top_level_gradle_build_file_migration.dart';
import 'package:flutter_tools/src/base/logger.dart'; import 'package:flutter_tools/src/base/logger.dart';
...@@ -47,8 +46,8 @@ zipStorePath=wrapper/dists ...@@ -47,8 +46,8 @@ zipStorePath=wrapper/dists
final Version androidStudioDolphin = Version(2021, 3, 1); final Version androidStudioDolphin = Version(2021, 3, 1);
final JavaVersion _javaVersion17 = JavaVersion(longText: 'openjdk 17.0.2', number: '17.0.2'); const Version _javaVersion17 = Version.withText(17, 0, 2, 'openjdk 17.0.2');
final JavaVersion _javaVersion16 = JavaVersion(longText: 'openjdk 16.0.2', number: '16.0.2'); const Version _javaVersion16 = Version.withText(16, 0, 2, 'openjdk 16.0.2');
void main() { void main() {
group('Android migration', () { group('Android migration', () {
...@@ -284,7 +283,7 @@ class FakeAndroidStudio extends Fake implements AndroidStudio { ...@@ -284,7 +283,7 @@ class FakeAndroidStudio extends Fake implements AndroidStudio {
class FakeErroringJava extends FakeJava { class FakeErroringJava extends FakeJava {
@override @override
JavaVersion get version { Version get version {
throw Exception('How did this happen?'); throw Exception('How did this happen?');
} }
} }
......
...@@ -384,7 +384,7 @@ void main() { ...@@ -384,7 +384,7 @@ void main() {
FileSystem: () => MemoryFileSystem.test(), FileSystem: () => MemoryFileSystem.test(),
ProcessManager: () => FakeProcessManager.empty(), ProcessManager: () => FakeProcessManager.empty(),
Platform: () => FakePlatform(environment: <String, String>{ Platform: () => FakePlatform(environment: <String, String>{
AndroidSdk.javaHomeEnvironmentVariable: 'java-home-path', Java.javaHomeEnvironmentVariable: 'java-home-path',
}), }),
Config: () => Config, Config: () => Config,
AndroidStudio: () => FakeAndroidStudioWithoutJdk(), AndroidStudio: () => FakeAndroidStudioWithoutJdk(),
......
...@@ -436,11 +436,9 @@ Review licenses that have not been accepted (y/N)? ...@@ -436,11 +436,9 @@ Review licenses that have not been accepted (y/N)?
..cmdlineToolsAvailable = true ..cmdlineToolsAvailable = true
..directory = fileSystem.directory('/foo/bar'); ..directory = fileSystem.directory('/foo/bar');
final ValidationResult validationResult = await AndroidValidator( final ValidationResult validationResult = await AndroidValidator(
androidStudio: FakeAndroidStudio(), java: FakeJava(),
androidSdk: sdk, androidSdk: sdk,
fileSystem: fileSystem,
logger: logger, logger: logger,
processManager: processManager,
platform: FakePlatform()..environment = <String, String>{'HOME': '/home/me'}, platform: FakePlatform()..environment = <String, String>{'HOME': '/home/me'},
userMessages: UserMessages(), userMessages: UserMessages(),
).validate(); ).validate();
...@@ -457,12 +455,6 @@ Review licenses that have not been accepted (y/N)? ...@@ -457,12 +455,6 @@ Review licenses that have not been accepted (y/N)?
}); });
testUsingContext('detects minimum required SDK and buildtools', () async { testUsingContext('detects minimum required SDK and buildtools', () async {
processManager.addCommand(const FakeCommand(
command: <String>[
'which',
'java',
], exitCode: 1,
));
final FakeAndroidSdkVersion sdkVersion = FakeAndroidSdkVersion() final FakeAndroidSdkVersion sdkVersion = FakeAndroidSdkVersion()
..sdkLevel = 28 ..sdkLevel = 28
..buildToolsVersion = Version(26, 0, 3); ..buildToolsVersion = Version(26, 0, 3);
...@@ -483,15 +475,14 @@ Review licenses that have not been accepted (y/N)? ...@@ -483,15 +475,14 @@ Review licenses that have not been accepted (y/N)?
); );
final AndroidValidator androidValidator = AndroidValidator( final AndroidValidator androidValidator = AndroidValidator(
androidStudio: null, java: null,
androidSdk: sdk, androidSdk: sdk,
fileSystem: fileSystem,
logger: logger, logger: logger,
processManager: processManager,
platform: FakePlatform()..environment = <String, String>{'HOME': '/home/me'}, platform: FakePlatform()..environment = <String, String>{'HOME': '/home/me'},
userMessages: UserMessages(), userMessages: UserMessages(),
); );
ValidationResult validationResult = await androidValidator.validate(); ValidationResult validationResult = await androidValidator.validate();
expect(validationResult.type, ValidationType.missing); expect(validationResult.type, ValidationType.missing);
expect( expect(
...@@ -531,15 +522,14 @@ Review licenses that have not been accepted (y/N)? ...@@ -531,15 +522,14 @@ Review licenses that have not been accepted (y/N)?
..directory = fileSystem.directory('/foo/bar'); ..directory = fileSystem.directory('/foo/bar');
final AndroidValidator androidValidator = AndroidValidator( final AndroidValidator androidValidator = AndroidValidator(
androidStudio: null, java: FakeJava(),
androidSdk: sdk, androidSdk: sdk,
fileSystem: fileSystem,
logger: logger, logger: logger,
processManager: processManager,
platform: FakePlatform()..environment = <String, String>{'HOME': '/home/me'}, platform: FakePlatform()..environment = <String, String>{'HOME': '/home/me'},
userMessages: UserMessages(), userMessages: UserMessages(),
); );
final String errorMessage = UserMessages().androidMissingCmdTools; final String errorMessage = UserMessages().androidMissingCmdTools;
final ValidationResult validationResult = await androidValidator.validate(); final ValidationResult validationResult = await androidValidator.validate();
...@@ -556,13 +546,11 @@ Review licenses that have not been accepted (y/N)? ...@@ -556,13 +546,11 @@ Review licenses that have not been accepted (y/N)?
testUsingContext('detects minimum required java version', () async { testUsingContext('detects minimum required java version', () async {
// Test with older version of JDK // Test with older version of JDK
const String javaVersionText = 'openjdk version "1.7.0_212"'; final Platform platform = FakePlatform()..environment = <String, String>{
processManager.addCommand(const FakeCommand( 'HOME': '/home/me',
command: <String>[ Java.javaHomeEnvironmentVariable: 'home/java',
'home/java/bin/java', 'PATH': '',
'-version', };
], stderr: javaVersionText,
));
final FakeAndroidSdkVersion sdkVersion = FakeAndroidSdkVersion() final FakeAndroidSdkVersion sdkVersion = FakeAndroidSdkVersion()
..sdkLevel = 29 ..sdkLevel = 29
..buildToolsVersion = Version(28, 0, 3); ..buildToolsVersion = Version(28, 0, 3);
...@@ -576,15 +564,14 @@ Review licenses that have not been accepted (y/N)? ...@@ -576,15 +564,14 @@ Review licenses that have not been accepted (y/N)?
..sdkManagerPath = '/foo/bar/sdkmanager'; ..sdkManagerPath = '/foo/bar/sdkmanager';
sdk.latestVersion = sdkVersion; sdk.latestVersion = sdkVersion;
const String javaVersionText = 'openjdk version "1.7.0_212"';
final String errorMessage = UserMessages().androidJavaMinimumVersion(javaVersionText); final String errorMessage = UserMessages().androidJavaMinimumVersion(javaVersionText);
final ValidationResult validationResult = await AndroidValidator( final ValidationResult validationResult = await AndroidValidator(
java: FakeJava(version: const Version.withText(1, 7, 0, javaVersionText)),
androidSdk: sdk, androidSdk: sdk,
androidStudio: null,
fileSystem: fileSystem,
logger: logger, logger: logger,
platform: FakePlatform()..environment = <String, String>{'HOME': '/home/me', AndroidSdk.javaHomeEnvironmentVariable: 'home/java'}, platform: platform,
processManager: processManager,
userMessages: UserMessages(), userMessages: UserMessages(),
).validate(); ).validate();
expect(validationResult.type, ValidationType.partial); expect(validationResult.type, ValidationType.partial);
...@@ -602,12 +589,10 @@ Review licenses that have not been accepted (y/N)? ...@@ -602,12 +589,10 @@ Review licenses that have not been accepted (y/N)?
testWithoutContext('Mentions `flutter config --android-sdk if user has no AndroidSdk`', () async { testWithoutContext('Mentions `flutter config --android-sdk if user has no AndroidSdk`', () async {
final ValidationResult validationResult = await AndroidValidator( final ValidationResult validationResult = await AndroidValidator(
java: FakeJava(),
androidSdk: null, androidSdk: null,
androidStudio: null,
fileSystem: fileSystem,
logger: logger, logger: logger,
platform: FakePlatform()..environment = <String, String>{'HOME': '/home/me', AndroidSdk.javaHomeEnvironmentVariable: 'home/java'}, platform: FakePlatform()..environment = <String, String>{'HOME': '/home/me', Java.javaHomeEnvironmentVariable: 'home/java'},
processManager: processManager,
userMessages: UserMessages(), userMessages: UserMessages(),
).validate(); ).validate();
......
...@@ -6,6 +6,7 @@ import 'package:file/memory.dart'; ...@@ -6,6 +6,7 @@ import 'package:file/memory.dart';
import 'package:file_testing/file_testing.dart'; import 'package:file_testing/file_testing.dart';
import 'package:flutter_tools/src/android/gradle_errors.dart'; import 'package:flutter_tools/src/android/gradle_errors.dart';
import 'package:flutter_tools/src/android/gradle_utils.dart'; import 'package:flutter_tools/src/android/gradle_utils.dart';
import 'package:flutter_tools/src/android/java.dart';
import 'package:flutter_tools/src/base/bot_detector.dart'; import 'package:flutter_tools/src/base/bot_detector.dart';
import 'package:flutter_tools/src/base/file_system.dart'; import 'package:flutter_tools/src/base/file_system.dart';
import 'package:flutter_tools/src/base/logger.dart'; import 'package:flutter_tools/src/base/logger.dart';
...@@ -774,6 +775,7 @@ assembleFooTest ...@@ -774,6 +775,7 @@ assembleFooTest
); );
expect(processManager, hasNoRemainingExpectations); expect(processManager, hasNoRemainingExpectations);
}, overrides: <Type, Generator>{ }, overrides: <Type, Generator>{
Java: () => FakeJava(),
GradleUtils: () => FakeGradleUtils(), GradleUtils: () => FakeGradleUtils(),
Platform: () => fakePlatform('android'), Platform: () => fakePlatform('android'),
FileSystem: () => fileSystem, FileSystem: () => fileSystem,
...@@ -816,6 +818,7 @@ assembleProfile ...@@ -816,6 +818,7 @@ assembleProfile
); );
expect(processManager, hasNoRemainingExpectations); expect(processManager, hasNoRemainingExpectations);
}, overrides: <Type, Generator>{ }, overrides: <Type, Generator>{
Java: () => FakeJava(),
GradleUtils: () => FakeGradleUtils(), GradleUtils: () => FakeGradleUtils(),
Platform: () => fakePlatform('android'), Platform: () => fakePlatform('android'),
FileSystem: () => fileSystem, FileSystem: () => fileSystem,
......
...@@ -9,6 +9,7 @@ import 'package:flutter_tools/src/base/file_system.dart'; ...@@ -9,6 +9,7 @@ import 'package:flutter_tools/src/base/file_system.dart';
import 'package:flutter_tools/src/base/logger.dart'; import 'package:flutter_tools/src/base/logger.dart';
import 'package:flutter_tools/src/base/os.dart'; import 'package:flutter_tools/src/base/os.dart';
import 'package:flutter_tools/src/base/platform.dart'; import 'package:flutter_tools/src/base/platform.dart';
import 'package:flutter_tools/src/base/version.dart';
import 'package:test/fake.dart'; import 'package:test/fake.dart';
import 'package:webdriver/async_io.dart'; import 'package:webdriver/async_io.dart';
...@@ -59,13 +60,12 @@ OpenJDK 64-Bit Server VM Zulu19.32+15-CA (build 19.0.2+7, mixed mode, sharing) ...@@ -59,13 +60,12 @@ OpenJDK 64-Bit Server VM Zulu19.32+15-CA (build 19.0.2+7, mixed mode, sharing)
platform: platform, platform: platform,
processManager: processManager, processManager: processManager,
)!; )!;
final JavaVersion version = java.version!;
expect(java.javaHome, androidStudioBundledJdkHome); expect(java.javaHome, androidStudioBundledJdkHome);
expect(java.binaryPath, expectedJavaBinaryPath); expect(java.binaryPath, expectedJavaBinaryPath);
expect(version.longText, 'OpenJDK Runtime Environment Zulu19.32+15-CA (build 19.0.2+7)'); expect(java.version!.toString(), 'OpenJDK Runtime Environment Zulu19.32+15-CA (build 19.0.2+7)');
expect(version.number, '19.0.2'); expect(java.version, equals(Version(19, 0, 2)));
}); });
testWithoutContext('finds JAVA_HOME if it is set and the JDK bundled with Android Studio could not be found', () { testWithoutContext('finds JAVA_HOME if it is set and the JDK bundled with Android Studio could not be found', () {
...@@ -78,7 +78,7 @@ OpenJDK 64-Bit Server VM Zulu19.32+15-CA (build 19.0.2+7, mixed mode, sharing) ...@@ -78,7 +78,7 @@ OpenJDK 64-Bit Server VM Zulu19.32+15-CA (build 19.0.2+7, mixed mode, sharing)
logger: logger, logger: logger,
fileSystem: fs, fileSystem: fs,
platform: FakePlatform(environment: <String, String>{ platform: FakePlatform(environment: <String, String>{
'JAVA_HOME': javaHome, Java.javaHomeEnvironmentVariable: javaHome,
}), }),
processManager: processManager, processManager: processManager,
)!; )!;
...@@ -160,9 +160,9 @@ java version "1.8.0_202" ...@@ -160,9 +160,9 @@ java version "1.8.0_202"
Java(TM) SE Runtime Environment (build 1.8.0_202-b10) Java(TM) SE Runtime Environment (build 1.8.0_202-b10)
Java HotSpot(TM) 64-Bit Server VM (build 25.202-b10, mixed mode) Java HotSpot(TM) 64-Bit Server VM (build 25.202-b10, mixed mode)
'''); ''');
final JavaVersion version = java.version!; final Version version = java.version!;
expect(version.longText, 'Java(TM) SE Runtime Environment (build 1.8.0_202-b10)'); expect(version.toString(), 'Java(TM) SE Runtime Environment (build 1.8.0_202-b10)');
expect(version.number, '1.8.0'); expect(version, equals(Version(1, 8, 0)));
}); });
testWithoutContext('parses jdk 11 windows', () { testWithoutContext('parses jdk 11 windows', () {
addJavaVersionCommand(''' addJavaVersionCommand('''
...@@ -170,9 +170,9 @@ java version "11.0.14" ...@@ -170,9 +170,9 @@ java version "11.0.14"
Java(TM) SE Runtime Environment (build 11.0.14+10-b13) Java(TM) SE Runtime Environment (build 11.0.14+10-b13)
Java HotSpot(TM) 64-Bit Server VM (build 11.0.14+10-b13, mixed mode) Java HotSpot(TM) 64-Bit Server VM (build 11.0.14+10-b13, mixed mode)
'''); ''');
final JavaVersion version = java.version!; final Version version = java.version!;
expect(version.longText, 'Java(TM) SE Runtime Environment (build 11.0.14+10-b13)'); expect(version.toString(), 'Java(TM) SE Runtime Environment (build 11.0.14+10-b13)');
expect(version.number, '11.0.14'); expect(version, equals(Version(11, 0, 14)));
}); });
testWithoutContext('parses jdk 11 mac/linux', () { testWithoutContext('parses jdk 11 mac/linux', () {
...@@ -181,9 +181,9 @@ openjdk version "11.0.18" 2023-01-17 LTS ...@@ -181,9 +181,9 @@ openjdk version "11.0.18" 2023-01-17 LTS
OpenJDK Runtime Environment Zulu11.62+17-CA (build 11.0.18+10-LTS) OpenJDK Runtime Environment Zulu11.62+17-CA (build 11.0.18+10-LTS)
OpenJDK 64-Bit Server VM Zulu11.62+17-CA (build 11.0.18+10-LTS, mixed mode) OpenJDK 64-Bit Server VM Zulu11.62+17-CA (build 11.0.18+10-LTS, mixed mode)
'''); ''');
final JavaVersion version = java.version!; final Version version = java.version!;
expect(version.longText, 'OpenJDK Runtime Environment Zulu11.62+17-CA (build 11.0.18+10-LTS)'); expect(version.toString(), 'OpenJDK Runtime Environment Zulu11.62+17-CA (build 11.0.18+10-LTS)');
expect(version.number, '11.0.18'); expect(version, equals(Version(11, 0, 18)));
}); });
testWithoutContext('parses jdk 17', () { testWithoutContext('parses jdk 17', () {
...@@ -192,9 +192,9 @@ openjdk 17.0.6 2023-01-17 ...@@ -192,9 +192,9 @@ openjdk 17.0.6 2023-01-17
OpenJDK Runtime Environment (build 17.0.6+0-17.0.6b802.4-9586694) OpenJDK Runtime Environment (build 17.0.6+0-17.0.6b802.4-9586694)
OpenJDK 64-Bit Server VM (build 17.0.6+0-17.0.6b802.4-9586694, mixed mode) OpenJDK 64-Bit Server VM (build 17.0.6+0-17.0.6b802.4-9586694, mixed mode)
'''); ''');
final JavaVersion version = java.version!; final Version version = java.version!;
expect(version.longText, 'OpenJDK Runtime Environment (build 17.0.6+0-17.0.6b802.4-9586694)'); expect(version.toString(), 'OpenJDK Runtime Environment (build 17.0.6+0-17.0.6b802.4-9586694)');
expect(version.number, '17.0.6'); expect(version, equals(Version(17, 0, 6)));
}); });
testWithoutContext('parses jdk 19', () { testWithoutContext('parses jdk 19', () {
...@@ -203,9 +203,9 @@ openjdk 19.0.2 2023-01-17 ...@@ -203,9 +203,9 @@ openjdk 19.0.2 2023-01-17
OpenJDK Runtime Environment Homebrew (build 19.0.2) OpenJDK Runtime Environment Homebrew (build 19.0.2)
OpenJDK 64-Bit Server VM Homebrew (build 19.0.2, mixed mode, sharing) OpenJDK 64-Bit Server VM Homebrew (build 19.0.2, mixed mode, sharing)
'''); ''');
final JavaVersion version = java.version!; final Version version = java.version!;
expect(version.longText, 'OpenJDK Runtime Environment Homebrew (build 19.0.2)'); expect(version.toString(), 'OpenJDK Runtime Environment Homebrew (build 19.0.2)');
expect(version.number, '19.0.2'); expect(version, equals(Version(19, 0, 2)));
}); });
// https://chrome-infra-packages.appspot.com/p/flutter/java/openjdk/ // https://chrome-infra-packages.appspot.com/p/flutter/java/openjdk/
...@@ -215,16 +215,16 @@ openjdk 11.0.2 2019-01-15 ...@@ -215,16 +215,16 @@ openjdk 11.0.2 2019-01-15
OpenJDK Runtime Environment 18.9 (build 11.0.2+9) OpenJDK Runtime Environment 18.9 (build 11.0.2+9)
OpenJDK 64-Bit Server VM 18.9 (build 11.0.2+9, mixed mode) OpenJDK 64-Bit Server VM 18.9 (build 11.0.2+9, mixed mode)
'''); ''');
final JavaVersion version = java.version!; final Version version = java.version!;
expect(version.longText, 'OpenJDK Runtime Environment 18.9 (build 11.0.2+9)'); expect(version.toString(), 'OpenJDK Runtime Environment 18.9 (build 11.0.2+9)');
expect(version.number, '11.0.2'); expect(version, equals(Version(11, 0, 2)));
}); });
testWithoutContext('parses jdk two number versions', () { testWithoutContext('parses jdk two number versions', () {
addJavaVersionCommand('openjdk 19.0 2023-01-17'); addJavaVersionCommand('openjdk 19.0 2023-01-17');
final JavaVersion version = java.version!; final Version version = java.version!;
expect(version.longText, 'openjdk 19.0 2023-01-17'); expect(version.toString(), 'openjdk 19.0 2023-01-17');
expect(version.number, '19.0'); expect(version, equals(Version(19, 0, null)));
}); });
}); });
}); });
......
...@@ -1042,7 +1042,11 @@ void main() { ...@@ -1042,7 +1042,11 @@ void main() {
}); });
testWithoutContext('AndroidMavenArtifacts has a specified development artifact', () async { testWithoutContext('AndroidMavenArtifacts has a specified development artifact', () async {
final AndroidMavenArtifacts mavenArtifacts = AndroidMavenArtifacts(cache!, platform: FakePlatform()); final AndroidMavenArtifacts mavenArtifacts = AndroidMavenArtifacts(
cache!,
java: FakeJava(),
platform: FakePlatform(),
);
expect(mavenArtifacts.developmentArtifact, DevelopmentArtifact.androidMaven); expect(mavenArtifacts.developmentArtifact, DevelopmentArtifact.androidMaven);
}); });
...@@ -1050,7 +1054,11 @@ void main() { ...@@ -1050,7 +1054,11 @@ void main() {
final String? oldRoot = Cache.flutterRoot; final String? oldRoot = Cache.flutterRoot;
Cache.flutterRoot = ''; Cache.flutterRoot = '';
try { try {
final AndroidMavenArtifacts mavenArtifacts = AndroidMavenArtifacts(cache!, platform: FakePlatform()); final AndroidMavenArtifacts mavenArtifacts = AndroidMavenArtifacts(
cache!,
java: FakeJava(),
platform: FakePlatform(),
);
expect(await mavenArtifacts.isUpToDate(memoryFileSystem!), isFalse); expect(await mavenArtifacts.isUpToDate(memoryFileSystem!), isFalse);
final Directory gradleWrapperDir = cache!.getArtifactDirectory('gradle_wrapper')..createSync(recursive: true); final Directory gradleWrapperDir = cache!.getArtifactDirectory('gradle_wrapper')..createSync(recursive: true);
...@@ -1082,7 +1090,11 @@ void main() { ...@@ -1082,7 +1090,11 @@ void main() {
}); });
testUsingContext('AndroidMavenArtifacts is a no-op if the Android SDK is absent', () async { testUsingContext('AndroidMavenArtifacts is a no-op if the Android SDK is absent', () async {
final AndroidMavenArtifacts mavenArtifacts = AndroidMavenArtifacts(cache!, platform: FakePlatform()); final AndroidMavenArtifacts mavenArtifacts = AndroidMavenArtifacts(
cache!,
java: FakeJava(),
platform: FakePlatform(),
);
expect(await mavenArtifacts.isUpToDate(memoryFileSystem!), isFalse); expect(await mavenArtifacts.isUpToDate(memoryFileSystem!), isFalse);
await mavenArtifacts.update(FakeArtifactUpdater(), BufferLogger.test(), memoryFileSystem!, FakeOperatingSystemUtils()); await mavenArtifacts.update(FakeArtifactUpdater(), BufferLogger.test(), memoryFileSystem!, FakeOperatingSystemUtils());
......
...@@ -11,6 +11,7 @@ import 'package:flutter_tools/src/android/java.dart'; ...@@ -11,6 +11,7 @@ import 'package:flutter_tools/src/android/java.dart';
import 'package:flutter_tools/src/base/file_system.dart'; import 'package:flutter_tools/src/base/file_system.dart';
import 'package:flutter_tools/src/base/logger.dart'; import 'package:flutter_tools/src/base/logger.dart';
import 'package:flutter_tools/src/base/os.dart'; import 'package:flutter_tools/src/base/os.dart';
import 'package:flutter_tools/src/base/version.dart';
import 'package:flutter_tools/src/build_info.dart'; import 'package:flutter_tools/src/build_info.dart';
import 'package:flutter_tools/src/cache.dart'; import 'package:flutter_tools/src/cache.dart';
import 'package:flutter_tools/src/convert.dart'; import 'package:flutter_tools/src/convert.dart';
...@@ -431,7 +432,7 @@ dependencies { ...@@ -431,7 +432,7 @@ dependencies {
final AndroidStudio androidStudio; final AndroidStudio androidStudio;
final FakeAndroidSdkWithDir androidSdk; final FakeAndroidSdkWithDir androidSdk;
final FileSystem fileSystem = getFileSystemForPlatform(); final FileSystem fileSystem = getFileSystemForPlatform();
java = FakeJava(version: JavaVersion(longText: '17.0.2', number: '17.0.2')); java = FakeJava(version: Version(17, 0, 2));
processManager = FakeProcessManager.empty(); processManager = FakeProcessManager.empty();
androidStudio = FakeAndroidStudio(); androidStudio = FakeAndroidStudio();
androidSdk = androidSdk =
...@@ -462,7 +463,7 @@ dependencies { ...@@ -462,7 +463,7 @@ dependencies {
final AndroidStudio androidStudio; final AndroidStudio androidStudio;
final FakeAndroidSdkWithDir androidSdk; final FakeAndroidSdkWithDir androidSdk;
final FileSystem fileSystem = getFileSystemForPlatform(); final FileSystem fileSystem = getFileSystemForPlatform();
java = FakeJava(version: JavaVersion(longText: '1.8.0_242', number: '1.8.0_242')); java = FakeJava(version: const Version.withText(1, 8, 0, '1.8.0_242'));
processManager = FakeProcessManager.empty(); processManager = FakeProcessManager.empty();
androidStudio = FakeAndroidStudio(); androidStudio = FakeAndroidStudio();
androidSdk = androidSdk =
...@@ -495,7 +496,7 @@ dependencies { ...@@ -495,7 +496,7 @@ dependencies {
final FakeAndroidSdkWithDir androidSdk; final FakeAndroidSdkWithDir androidSdk;
final FileSystem fileSystem = getFileSystemForPlatform(); final FileSystem fileSystem = getFileSystemForPlatform();
processManager = FakeProcessManager.empty(); processManager = FakeProcessManager.empty();
java = FakeJava(version: JavaVersion(longText: '11.0.14', number: '11.0.14')); java = FakeJava(version: Version(11, 0, 14));
androidStudio = FakeAndroidStudio(); androidStudio = FakeAndroidStudio();
androidSdk = androidSdk =
FakeAndroidSdkWithDir(fileSystem.currentDirectory); FakeAndroidSdkWithDir(fileSystem.currentDirectory);
...@@ -530,7 +531,7 @@ dependencies { ...@@ -530,7 +531,7 @@ dependencies {
final FakeAndroidSdkWithDir androidSdk; final FakeAndroidSdkWithDir androidSdk;
final FileSystem fileSystem = getFileSystemForPlatform(); final FileSystem fileSystem = getFileSystemForPlatform();
processManager = FakeProcessManager.empty(); processManager = FakeProcessManager.empty();
java = FakeJava(version: JavaVersion(longText: javaV, number: javaV)); java = FakeJava(version: Version.parse(javaV));
androidStudio = FakeAndroidStudio(); androidStudio = FakeAndroidStudio();
androidSdk = androidSdk =
FakeAndroidSdkWithDir(fileSystem.currentDirectory); FakeAndroidSdkWithDir(fileSystem.currentDirectory);
...@@ -581,7 +582,7 @@ dependencies { ...@@ -581,7 +582,7 @@ dependencies {
final FakeAndroidSdkWithDir androidSdk; final FakeAndroidSdkWithDir androidSdk;
final FileSystem fileSystem = getFileSystemForPlatform(); final FileSystem fileSystem = getFileSystemForPlatform();
processManager = FakeProcessManager.empty(); processManager = FakeProcessManager.empty();
java = FakeJava(version: JavaVersion(longText: '17.0.2', number: '17.0.2')); java = FakeJava(version: Version(17, 0, 2));
androidStudio = FakeAndroidStudio(); androidStudio = FakeAndroidStudio();
androidSdk = androidSdk =
FakeAndroidSdkWithDir(fileSystem.currentDirectory); FakeAndroidSdkWithDir(fileSystem.currentDirectory);
...@@ -621,7 +622,7 @@ dependencies { ...@@ -621,7 +622,7 @@ dependencies {
final AndroidStudio androidStudio; final AndroidStudio androidStudio;
final FakeAndroidSdkWithDir androidSdk; final FakeAndroidSdkWithDir androidSdk;
final FileSystem fileSystem = getFileSystemForPlatform(); final FileSystem fileSystem = getFileSystemForPlatform();
java = FakeJava(version: JavaVersion(longText: '11.0.2', number: '11.0.2')); java = FakeJava(version: Version(11, 0, 2));
processManager = FakeProcessManager.empty(); processManager = FakeProcessManager.empty();
androidStudio = FakeAndroidStudio(); androidStudio = FakeAndroidStudio();
androidSdk = androidSdk =
......
...@@ -13,6 +13,7 @@ import 'package:flutter_tools/src/base/file_system.dart'; ...@@ -13,6 +13,7 @@ import 'package:flutter_tools/src/base/file_system.dart';
import 'package:flutter_tools/src/base/io.dart'; import 'package:flutter_tools/src/base/io.dart';
import 'package:flutter_tools/src/base/logger.dart'; import 'package:flutter_tools/src/base/logger.dart';
import 'package:flutter_tools/src/base/os.dart'; import 'package:flutter_tools/src/base/os.dart';
import 'package:flutter_tools/src/base/version.dart';
import 'package:flutter_tools/src/cache.dart'; import 'package:flutter_tools/src/cache.dart';
import 'package:flutter_tools/src/convert.dart'; import 'package:flutter_tools/src/convert.dart';
import 'package:flutter_tools/src/features.dart'; import 'package:flutter_tools/src/features.dart';
...@@ -619,15 +620,12 @@ class FakeJava extends Fake implements Java { ...@@ -619,15 +620,12 @@ class FakeJava extends Fake implements Java {
FakeJava({ FakeJava({
this.javaHome = '/android-studio/jbr', this.javaHome = '/android-studio/jbr',
String binary = '/android-studio/jbr/bin/java', String binary = '/android-studio/jbr/bin/java',
JavaVersion? version, Version? version,
bool canRun = true, bool canRun = true,
}): binaryPath = binary, }): binaryPath = binary,
version = version ?? JavaVersion( version = version ?? const Version.withText(19, 0, 2, 'openjdk 19.0.2 2023-01-17'),
longText: 'openjdk 19.0.2 2023-01-17',
number: '19.0.2',
),
_environment = <String, String>{ _environment = <String, String>{
if (javaHome != null) 'JAVA_HOME': javaHome, if (javaHome != null) Java.javaHomeEnvironmentVariable: javaHome,
'PATH': '/android-studio/jbr/bin', 'PATH': '/android-studio/jbr/bin',
}, },
_canRun = canRun; _canRun = canRun;
...@@ -645,7 +643,7 @@ class FakeJava extends Fake implements Java { ...@@ -645,7 +643,7 @@ class FakeJava extends Fake implements Java {
Map<String, String> get environment => _environment; Map<String, String> get environment => _environment;
@override @override
JavaVersion? version; Version? version;
@override @override
bool canRun() { bool canRun() {
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment