[tool] Move Java functions to their own file (#126086)
This is the first step in unifying Java-finding logic across the tool. If curious, see #126029 for an example of what all the changes will probably entail. Moves java-related functionality like `AndroidSdk.findJavaHome` to a new class, `Java`. See tracking issue https://github.com/flutter/flutter/issues/126126 for more.
This commit is contained in:
parent
a308666d64
commit
0a63cd70f1
@ -2,17 +2,13 @@
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
import 'package:meta/meta.dart';
|
||||
|
||||
import '../base/common.dart';
|
||||
import '../base/file_system.dart';
|
||||
import '../base/os.dart';
|
||||
import '../base/platform.dart';
|
||||
import '../base/process.dart';
|
||||
import '../base/version.dart';
|
||||
import '../convert.dart';
|
||||
import '../globals.dart' as globals;
|
||||
import 'android_studio.dart';
|
||||
import 'java.dart';
|
||||
|
||||
// ANDROID_HOME is deprecated.
|
||||
// See https://developer.android.com/studio/command-line/variables.html#envar
|
||||
@ -36,16 +32,18 @@ final RegExp _sdkVersionRe = RegExp(r'^ro.build.version.sdk=([0-9]+)$');
|
||||
// $ANDROID_SDK_ROOT/platforms/android-23/android.jar
|
||||
// $ANDROID_SDK_ROOT/platforms/android-N/android.jar
|
||||
class AndroidSdk {
|
||||
AndroidSdk(this.directory) {
|
||||
AndroidSdk(this.directory, {
|
||||
Java? java,
|
||||
}): _java = java {
|
||||
reinitialize();
|
||||
}
|
||||
|
||||
static const String javaHomeEnvironmentVariable = 'JAVA_HOME';
|
||||
static const String _javaExecutable = 'java';
|
||||
|
||||
/// The Android SDK root directory.
|
||||
final Directory directory;
|
||||
|
||||
final Java? _java;
|
||||
|
||||
List<AndroidSdkVersion> _sdkVersions = <AndroidSdkVersion>[];
|
||||
AndroidSdkVersion? _latestVersion;
|
||||
|
||||
@ -411,162 +409,6 @@ class AndroidSdk {
|
||||
return null;
|
||||
}
|
||||
|
||||
/// Returns the version of java in the format \d(.\d)+(.\d)+
|
||||
/// Returns null if version not found.
|
||||
String? getJavaVersion({
|
||||
required AndroidStudio? androidStudio,
|
||||
required FileSystem fileSystem,
|
||||
required OperatingSystemUtils operatingSystemUtils,
|
||||
required Platform platform,
|
||||
required ProcessUtils processUtils,
|
||||
}) {
|
||||
final String? javaBinary = findJavaBinary(
|
||||
androidStudio: androidStudio,
|
||||
fileSystem: fileSystem,
|
||||
operatingSystemUtils: operatingSystemUtils,
|
||||
platform: platform,
|
||||
);
|
||||
if (javaBinary == null) {
|
||||
globals.printTrace('Could not find java binary to get version.');
|
||||
return null;
|
||||
}
|
||||
final RunResult result = processUtils.runSync(
|
||||
<String>[javaBinary, '--version'],
|
||||
environment: sdkManagerEnv,
|
||||
);
|
||||
if (result.exitCode != 0) {
|
||||
globals.printTrace(
|
||||
'java --version failed: exitCode: ${result.exitCode} stdout: ${result.stdout} stderr: ${result.stderr}');
|
||||
return null;
|
||||
}
|
||||
return parseJavaVersion(result.stdout);
|
||||
}
|
||||
|
||||
/// Extracts JDK version from the output of java --version.
|
||||
@visibleForTesting
|
||||
static String? parseJavaVersion(String rawVersionOutput) {
|
||||
// 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) {
|
||||
globals.logger.printWarning(_formatJavaVersionWarning(rawVersionOutput));
|
||||
return null;
|
||||
}
|
||||
final String? versionString = matches.first.group(0);
|
||||
if (versionString == null || versionString.split('_').isEmpty) {
|
||||
globals.logger.printWarning(_formatJavaVersionWarning(rawVersionOutput));
|
||||
return null;
|
||||
}
|
||||
// Trim away _d+ from versions 1.8 and below.
|
||||
return versionString.split('_').first;
|
||||
}
|
||||
|
||||
/// A value that would be appropriate to use as JAVA_HOME.
|
||||
///
|
||||
/// This method considers jdk in the following order:
|
||||
/// * the JDK bundled with Android Studio, if one is found;
|
||||
/// * the JAVA_HOME in the ambient environment, if set;
|
||||
String? get javaHome {
|
||||
return findJavaHome(
|
||||
androidStudio: globals.androidStudio,
|
||||
fileSystem: globals.fs,
|
||||
operatingSystemUtils: globals.os,
|
||||
platform: globals.platform,
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
static String? findJavaHome({
|
||||
required AndroidStudio? androidStudio,
|
||||
required FileSystem fileSystem,
|
||||
required OperatingSystemUtils operatingSystemUtils,
|
||||
required Platform platform,
|
||||
}) {
|
||||
if (androidStudio?.javaPath != null) {
|
||||
globals.printTrace("Using Android Studio's java.");
|
||||
return androidStudio!.javaPath!;
|
||||
}
|
||||
|
||||
final String? javaHomeEnv = platform.environment[javaHomeEnvironmentVariable];
|
||||
if (javaHomeEnv != null) {
|
||||
globals.printTrace('Using JAVA_HOME from environment valuables.');
|
||||
return javaHomeEnv;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/// Finds the java binary that is used for all operations across the tool.
|
||||
///
|
||||
/// This comes from [findJavaHome] if that method returns non-null;
|
||||
/// otherwise, it gets from searching PATH.
|
||||
// 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 String? findJavaBinary({
|
||||
required AndroidStudio? androidStudio,
|
||||
required FileSystem fileSystem,
|
||||
required OperatingSystemUtils operatingSystemUtils,
|
||||
required Platform platform,
|
||||
}) {
|
||||
final String? javaHome = findJavaHome(
|
||||
androidStudio: androidStudio,
|
||||
fileSystem: fileSystem,
|
||||
operatingSystemUtils: operatingSystemUtils,
|
||||
platform: platform,
|
||||
);
|
||||
|
||||
if (javaHome != null) {
|
||||
return fileSystem.path.join(javaHome, 'bin', 'java');
|
||||
}
|
||||
|
||||
// Fallback to PATH based lookup.
|
||||
final String? pathJava = operatingSystemUtils.which(_javaExecutable)?.path;
|
||||
if (pathJava != null) {
|
||||
globals.printTrace('Using java from PATH.');
|
||||
} else {
|
||||
globals.printTrace('Could not find java path.');
|
||||
}
|
||||
return pathJava;
|
||||
}
|
||||
|
||||
// Returns a user visible String that says the tool failed to parse
|
||||
// the version of java along with the output.
|
||||
static String _formatJavaVersionWarning(String javaVersionRaw) {
|
||||
return 'Could not parse java version from: \n'
|
||||
'$javaVersionRaw \n'
|
||||
'If there is a version please look for an existing bug '
|
||||
'https://github.com/flutter/flutter/issues/'
|
||||
' and if one does not exist file a new issue.';
|
||||
}
|
||||
|
||||
Map<String, String>? _sdkManagerEnv;
|
||||
|
||||
/// Returns an environment with the Java folder added to PATH for use in calling
|
||||
/// Java-based Android SDK commands such as sdkmanager and avdmanager.
|
||||
Map<String, String> get sdkManagerEnv {
|
||||
if (_sdkManagerEnv == null) {
|
||||
// If we can locate Java, then add it to the path used to run the Android SDK manager.
|
||||
_sdkManagerEnv = <String, String>{};
|
||||
final String? javaBinary = findJavaBinary(
|
||||
androidStudio: globals.androidStudio,
|
||||
fileSystem: globals.fs,
|
||||
operatingSystemUtils: globals.os,
|
||||
platform: globals.platform,
|
||||
);
|
||||
if (javaBinary != null && globals.platform.environment['PATH'] != null) {
|
||||
_sdkManagerEnv!['PATH'] = globals.fs.path.dirname(javaBinary) +
|
||||
globals.os.pathVarSeparator +
|
||||
globals.platform.environment['PATH']!;
|
||||
}
|
||||
}
|
||||
return _sdkManagerEnv!;
|
||||
}
|
||||
|
||||
/// Returns the version of the Android SDK manager tool or null if not found.
|
||||
String? get sdkManagerVersion {
|
||||
if (sdkManagerPath == null || !globals.processManager.canRun(sdkManagerPath)) {
|
||||
@ -577,7 +419,7 @@ class AndroidSdk {
|
||||
}
|
||||
final RunResult result = globals.processUtils.runSync(
|
||||
<String>[sdkManagerPath!, '--version'],
|
||||
environment: sdkManagerEnv,
|
||||
environment: _java?.environment,
|
||||
);
|
||||
if (result.exitCode != 0) {
|
||||
globals.printTrace('sdkmanager --version failed: exitCode: ${result.exitCode} stdout: ${result.stdout} stderr: ${result.stderr}');
|
||||
|
@ -11,7 +11,6 @@ import '../base/context.dart';
|
||||
import '../base/file_system.dart';
|
||||
import '../base/io.dart';
|
||||
import '../base/logger.dart';
|
||||
import '../base/os.dart';
|
||||
import '../base/platform.dart';
|
||||
import '../base/user_messages.dart' hide userMessages;
|
||||
import '../base/version.dart';
|
||||
@ -20,6 +19,7 @@ import '../doctor_validator.dart';
|
||||
import '../features.dart';
|
||||
import 'android_sdk.dart';
|
||||
import 'android_studio.dart';
|
||||
import 'java.dart';
|
||||
|
||||
const int kAndroidSdkMinVersion = 29;
|
||||
final Version kAndroidJavaMinVersion = Version(1, 8, 0);
|
||||
@ -86,12 +86,6 @@ class AndroidValidator extends DoctorValidator {
|
||||
_androidStudio = androidStudio,
|
||||
_fileSystem = fileSystem,
|
||||
_logger = logger,
|
||||
_operatingSystemUtils = OperatingSystemUtils(
|
||||
fileSystem: fileSystem,
|
||||
logger: logger,
|
||||
platform: platform,
|
||||
processManager: processManager,
|
||||
),
|
||||
_platform = platform,
|
||||
_processManager = processManager,
|
||||
_userMessages = userMessages,
|
||||
@ -101,7 +95,6 @@ class AndroidValidator extends DoctorValidator {
|
||||
final AndroidStudio? _androidStudio;
|
||||
final FileSystem _fileSystem;
|
||||
final Logger _logger;
|
||||
final OperatingSystemUtils _operatingSystemUtils;
|
||||
final Platform _platform;
|
||||
final ProcessManager _processManager;
|
||||
final UserMessages _userMessages;
|
||||
@ -138,6 +131,8 @@ class AndroidValidator extends DoctorValidator {
|
||||
}
|
||||
String? javaVersionText;
|
||||
try {
|
||||
// TODO(andrewkolos): Use Java class to find version instead of using duplicate
|
||||
// code. See https://github.com/flutter/flutter/issues/124252.
|
||||
_logger.printTrace('java -version');
|
||||
final ProcessResult result = await _processManager.run(<String>[javaBinary, '-version']);
|
||||
if (result.exitCode == 0) {
|
||||
@ -240,12 +235,13 @@ class AndroidValidator extends DoctorValidator {
|
||||
|
||||
_task = 'Finding Java binary';
|
||||
// Now check for the JDK.
|
||||
final String? javaBinary = AndroidSdk.findJavaBinary(
|
||||
final String? javaBinary = Java.find(
|
||||
logger: _logger,
|
||||
androidStudio: _androidStudio,
|
||||
fileSystem: _fileSystem,
|
||||
operatingSystemUtils: _operatingSystemUtils,
|
||||
platform: _platform,
|
||||
);
|
||||
processManager: _processManager,
|
||||
)?.binaryPath;
|
||||
if (javaBinary == null) {
|
||||
messages.add(ValidationMessage.error(_userMessages.androidMissingJdk));
|
||||
return ValidationResult(ValidationType.partial, messages, statusInfo: sdkVersionText);
|
||||
@ -266,18 +262,18 @@ class AndroidValidator extends DoctorValidator {
|
||||
/// SDK have been accepted.
|
||||
class AndroidLicenseValidator extends DoctorValidator {
|
||||
AndroidLicenseValidator({
|
||||
required Java? java,
|
||||
required AndroidSdk? androidSdk,
|
||||
required Platform platform,
|
||||
required OperatingSystemUtils operatingSystemUtils,
|
||||
required FileSystem fileSystem,
|
||||
required ProcessManager processManager,
|
||||
required Logger logger,
|
||||
required AndroidStudio? androidStudio,
|
||||
required Stdio stdio,
|
||||
required UserMessages userMessages,
|
||||
}) : _androidSdk = androidSdk,
|
||||
}) : _java = java,
|
||||
_androidSdk = androidSdk,
|
||||
_platform = platform,
|
||||
_operatingSystemUtils = operatingSystemUtils,
|
||||
_fileSystem = fileSystem,
|
||||
_processManager = processManager,
|
||||
_logger = logger,
|
||||
@ -286,10 +282,10 @@ class AndroidLicenseValidator extends DoctorValidator {
|
||||
_userMessages = userMessages,
|
||||
super('Android license subvalidator');
|
||||
|
||||
final Java? _java;
|
||||
final AndroidSdk? _androidSdk;
|
||||
final AndroidStudio? _androidStudio;
|
||||
final Stdio _stdio;
|
||||
final OperatingSystemUtils _operatingSystemUtils;
|
||||
final Platform _platform;
|
||||
final FileSystem _fileSystem;
|
||||
final ProcessManager _processManager;
|
||||
@ -330,12 +326,13 @@ class AndroidLicenseValidator extends DoctorValidator {
|
||||
}
|
||||
|
||||
Future<bool> _checkJavaVersionNoOutput() async {
|
||||
final String? javaBinary = AndroidSdk.findJavaBinary(
|
||||
final String? javaBinary = Java.find(
|
||||
logger: _logger,
|
||||
androidStudio: _androidStudio,
|
||||
fileSystem: _fileSystem,
|
||||
operatingSystemUtils: _operatingSystemUtils,
|
||||
platform: _platform,
|
||||
);
|
||||
processManager: _processManager,
|
||||
)?.binaryPath;
|
||||
if (javaBinary == null) {
|
||||
return false;
|
||||
}
|
||||
@ -387,7 +384,7 @@ class AndroidLicenseValidator extends DoctorValidator {
|
||||
try {
|
||||
final Process process = await _processManager.start(
|
||||
<String>[_androidSdk!.sdkManagerPath!, '--licenses'],
|
||||
environment: _androidSdk!.sdkManagerEnv,
|
||||
environment: _java?.environment,
|
||||
);
|
||||
process.stdin.write('n\n');
|
||||
// We expect logcat streams to occasionally contain invalid utf-8,
|
||||
@ -427,7 +424,7 @@ class AndroidLicenseValidator extends DoctorValidator {
|
||||
try {
|
||||
final Process process = await _processManager.start(
|
||||
<String>[_androidSdk!.sdkManagerPath!, '--licenses'],
|
||||
environment: _androidSdk!.sdkManagerEnv,
|
||||
environment: _java?.environment,
|
||||
);
|
||||
|
||||
// The real stdin will never finish streaming. Pipe until the child process
|
||||
|
@ -147,8 +147,7 @@ class AndroidGradleBuilder implements AndroidBuilder {
|
||||
_gradleUtils = gradleUtils,
|
||||
_androidStudio = androidStudio,
|
||||
_fileSystemUtils = FileSystemUtils(fileSystem: fileSystem, platform: platform),
|
||||
_processUtils = ProcessUtils(logger: logger, processManager: processManager),
|
||||
_platform = platform;
|
||||
_processUtils = ProcessUtils(logger: logger, processManager: processManager);
|
||||
|
||||
final Logger _logger;
|
||||
final ProcessUtils _processUtils;
|
||||
@ -158,7 +157,6 @@ class AndroidGradleBuilder implements AndroidBuilder {
|
||||
final GradleUtils _gradleUtils;
|
||||
final FileSystemUtils _fileSystemUtils;
|
||||
final AndroidStudio? _androidStudio;
|
||||
final Platform _platform;
|
||||
|
||||
/// Builds the AAR and POM files for the current Flutter module or plugin.
|
||||
@override
|
||||
@ -268,11 +266,7 @@ class AndroidGradleBuilder implements AndroidBuilder {
|
||||
AndroidStudioJavaGradleConflictMigration(_logger,
|
||||
project: project.android,
|
||||
androidStudio: _androidStudio,
|
||||
fileSystem: _fileSystem,
|
||||
processUtils: _processUtils,
|
||||
platform: _platform,
|
||||
os: globals.os,
|
||||
androidSdk: globals.androidSdk)
|
||||
java: globals.java)
|
||||
,
|
||||
];
|
||||
|
||||
@ -428,7 +422,7 @@ class AndroidGradleBuilder implements AndroidBuilder {
|
||||
..start();
|
||||
int exitCode = 1;
|
||||
try {
|
||||
final String? javaHome = globals.androidSdk?.javaHome;
|
||||
final String? javaHome = globals.java?.javaHome;
|
||||
exitCode = await _processUtils.stream(
|
||||
command,
|
||||
workingDirectory: project.android.hostAppGradleRoot.path,
|
||||
@ -698,7 +692,7 @@ class AndroidGradleBuilder implements AndroidBuilder {
|
||||
..start();
|
||||
RunResult result;
|
||||
try {
|
||||
final String? javaHome = globals.androidSdk?.javaHome;
|
||||
final String? javaHome = globals.java?.javaHome;
|
||||
result = await _processUtils.run(
|
||||
command,
|
||||
workingDirectory: project.android.hostAppGradleRoot.path,
|
||||
@ -751,7 +745,7 @@ class AndroidGradleBuilder implements AndroidBuilder {
|
||||
..start();
|
||||
RunResult result;
|
||||
try {
|
||||
final String? javaHome = globals.androidSdk?.javaHome;
|
||||
final String? javaHome = globals.java?.javaHome;
|
||||
result = await _processUtils.run(
|
||||
command,
|
||||
workingDirectory: project.android.hostAppGradleRoot.path,
|
||||
|
230
packages/flutter_tools/lib/src/android/java.dart
Normal file
230
packages/flutter_tools/lib/src/android/java.dart
Normal file
@ -0,0 +1,230 @@
|
||||
// Copyright 2014 The Flutter Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
import 'package:process/process.dart';
|
||||
|
||||
import '../base/file_system.dart';
|
||||
import '../base/logger.dart';
|
||||
import '../base/os.dart';
|
||||
import '../base/platform.dart';
|
||||
import '../base/process.dart';
|
||||
import 'android_studio.dart';
|
||||
|
||||
const String _javaHomeEnvironmentVariable = 'JAVA_HOME';
|
||||
const String _kJavaExecutable = 'java';
|
||||
|
||||
/// Represents an installation of Java.
|
||||
class Java {
|
||||
Java({
|
||||
required this.javaHome,
|
||||
required this.binaryPath,
|
||||
required Logger logger,
|
||||
required FileSystem fileSystem,
|
||||
required OperatingSystemUtils os,
|
||||
required Platform platform,
|
||||
required ProcessManager processManager,
|
||||
}): _logger = logger,
|
||||
_fileSystem = fileSystem,
|
||||
_os = os,
|
||||
_platform = platform,
|
||||
_processManager = processManager,
|
||||
_processUtils = ProcessUtils(processManager: processManager, logger: logger);
|
||||
|
||||
/// Finds the Java runtime environment that should be used for all java-dependent
|
||||
/// operations across the tool.
|
||||
///
|
||||
/// This searches for Java in the following places, in order:
|
||||
///
|
||||
/// 1. the runtime environment bundled with Android Studio;
|
||||
/// 2. the runtime environment found in the JAVA_HOME env variable, if set; or
|
||||
/// 3. the java binary found on PATH.
|
||||
///
|
||||
/// 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({
|
||||
required AndroidStudio? androidStudio,
|
||||
required Logger logger,
|
||||
required FileSystem fileSystem,
|
||||
required Platform platform,
|
||||
required ProcessManager processManager,
|
||||
}) {
|
||||
final OperatingSystemUtils os = OperatingSystemUtils(
|
||||
fileSystem: fileSystem,
|
||||
logger: logger,
|
||||
platform: platform,
|
||||
processManager: processManager
|
||||
);
|
||||
final String? home = _findJavaHome(
|
||||
logger: logger,
|
||||
androidStudio: androidStudio,
|
||||
platform: platform
|
||||
);
|
||||
final String? binary = _findJavaBinary(
|
||||
logger: logger,
|
||||
javaHome: home,
|
||||
fileSystem: fileSystem,
|
||||
operatingSystemUtils: os,
|
||||
platform: platform
|
||||
);
|
||||
|
||||
if (binary == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return Java(
|
||||
javaHome: home,
|
||||
binaryPath: binary,
|
||||
logger: logger,
|
||||
fileSystem: fileSystem,
|
||||
os: os,
|
||||
platform: platform,
|
||||
processManager: processManager,
|
||||
);
|
||||
}
|
||||
|
||||
/// The path of the runtime's home directory.
|
||||
///
|
||||
/// This should only be used for logging and validation purposes.
|
||||
/// If you need to set JAVA_HOME when starting a process, consider
|
||||
/// using [environment] instead.
|
||||
/// If you need to inspect the files of the runtime, considering adding
|
||||
/// a new method to this class instead.
|
||||
final String? javaHome;
|
||||
|
||||
/// The path of the runtime's java binary.
|
||||
///
|
||||
/// This should be only used for logging and validation purposes.
|
||||
/// If you need to invoke the binary directly, consider adding a new method
|
||||
/// to this class instead.
|
||||
final String binaryPath;
|
||||
|
||||
final Logger _logger;
|
||||
final FileSystem _fileSystem;
|
||||
final OperatingSystemUtils _os;
|
||||
final Platform _platform;
|
||||
final ProcessManager _processManager;
|
||||
final ProcessUtils _processUtils;
|
||||
|
||||
/// Returns an environment variable map with
|
||||
/// 1. JAVA_HOME set if this object has a known home directory, and
|
||||
/// 2. The java binary folder appended onto PATH, if the binary location is known.
|
||||
///
|
||||
/// This map should be used as the environment when invoking any Java-dependent
|
||||
/// processes, such as Gradle or Android SDK tools (avdmanager, sdkmanager, etc.)
|
||||
Map<String, String> get environment {
|
||||
return <String, String>{
|
||||
if (javaHome != null) _javaHomeEnvironmentVariable: javaHome!,
|
||||
'PATH': _fileSystem.path.dirname(binaryPath) +
|
||||
_os.pathVarSeparator +
|
||||
_platform.environment['PATH']!,
|
||||
};
|
||||
}
|
||||
|
||||
/// Returns the version of java in the format \d(.\d)+(.\d)+
|
||||
/// Returns null if version could not be determined.
|
||||
late final JavaVersion? version = (() {
|
||||
final RunResult result = _processUtils.runSync(
|
||||
<String>[binaryPath, '--version'],
|
||||
environment: environment,
|
||||
);
|
||||
if (result.exitCode != 0) {
|
||||
_logger.printTrace('java --version failed: exitCode: ${result.exitCode}'
|
||||
' stdout: ${result.stdout} stderr: ${result.stderr}');
|
||||
}
|
||||
return JavaVersion.tryParseFromJavaOutput(result.stdout, logger: _logger);
|
||||
})();
|
||||
|
||||
bool canRun() {
|
||||
return _processManager.canRun(binaryPath);
|
||||
}
|
||||
}
|
||||
|
||||
String? _findJavaHome({
|
||||
required Logger logger,
|
||||
required AndroidStudio? androidStudio,
|
||||
required Platform platform,
|
||||
}) {
|
||||
final String? androidStudioJavaPath = androidStudio?.javaPath;
|
||||
if (androidStudioJavaPath != null) {
|
||||
return androidStudioJavaPath;
|
||||
}
|
||||
|
||||
final String? javaHomeEnv = platform.environment[_javaHomeEnvironmentVariable];
|
||||
if (javaHomeEnv != null) {
|
||||
return javaHomeEnv;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
String? _findJavaBinary({
|
||||
required Logger logger,
|
||||
required String? javaHome,
|
||||
required FileSystem fileSystem,
|
||||
required OperatingSystemUtils operatingSystemUtils,
|
||||
required Platform platform,
|
||||
}) {
|
||||
if (javaHome != null) {
|
||||
return fileSystem.path.join(javaHome, 'bin', 'java');
|
||||
}
|
||||
|
||||
// Fallback to PATH based lookup.
|
||||
return operatingSystemUtils.which(_kJavaExecutable)?.path;
|
||||
}
|
||||
|
||||
// Returns a user visible String that says the tool failed to parse
|
||||
// the version of java along with the output.
|
||||
String _formatJavaVersionWarning(String javaVersionRaw) {
|
||||
return 'Could not parse java version from: \n'
|
||||
'$javaVersionRaw \n'
|
||||
'If there is a version please look for an existing bug '
|
||||
'https://github.com/flutter/flutter/issues/ '
|
||||
'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);
|
||||
}
|
||||
}
|
@ -5,15 +5,12 @@
|
||||
import 'package:meta/meta.dart';
|
||||
|
||||
import '../../base/file_system.dart';
|
||||
import '../../base/os.dart';
|
||||
import '../../base/platform.dart';
|
||||
import '../../base/process.dart';
|
||||
import '../../base/project_migrator.dart';
|
||||
import '../../base/version.dart';
|
||||
import '../../project.dart';
|
||||
import '../android_sdk.dart';
|
||||
import '../android_studio.dart';
|
||||
import '../gradle_utils.dart';
|
||||
import '../java.dart';
|
||||
|
||||
// Android Studio 2022.2 "Flamingo" is the first to bundle a Java 17 JDK.
|
||||
// Previous versions bundled a Java 11 JDK.
|
||||
@ -77,25 +74,14 @@ class AndroidStudioJavaGradleConflictMigration extends ProjectMigrator {
|
||||
super.logger,
|
||||
{required AndroidProject project,
|
||||
AndroidStudio? androidStudio,
|
||||
required FileSystem fileSystem,
|
||||
required ProcessUtils processUtils,
|
||||
required Platform platform,
|
||||
required OperatingSystemUtils os,
|
||||
AndroidSdk? androidSdk,
|
||||
required Java? java,
|
||||
}) : _gradleWrapperPropertiesFile = getGradleWrapperFile(project.hostAppGradleRoot),
|
||||
_androidStudio = androidStudio,
|
||||
_fileSystem = fileSystem,
|
||||
_processUtils = processUtils,
|
||||
_platform = platform,
|
||||
_os = os,
|
||||
_androidSdk = androidSdk;
|
||||
_java = java;
|
||||
|
||||
final File _gradleWrapperPropertiesFile;
|
||||
final AndroidStudio? _androidStudio;
|
||||
final FileSystem _fileSystem;
|
||||
final ProcessUtils _processUtils;
|
||||
final Platform _platform;
|
||||
final OperatingSystemUtils _os;
|
||||
final AndroidSdk? _androidSdk;
|
||||
final Java? _java;
|
||||
|
||||
@override
|
||||
void migrate() {
|
||||
@ -113,13 +99,7 @@ class AndroidStudioJavaGradleConflictMigration extends ProjectMigrator {
|
||||
return;
|
||||
}
|
||||
|
||||
final String? javaVersionString = _androidSdk?.getJavaVersion(
|
||||
androidStudio: _androidStudio,
|
||||
fileSystem: _fileSystem,
|
||||
operatingSystemUtils: _os,
|
||||
platform: _platform,
|
||||
processUtils: _processUtils,
|
||||
);
|
||||
final String? javaVersionString = _java?.version?.number;
|
||||
final Version? javaVersion = Version.parse(javaVersionString);
|
||||
if (javaVersion == null) {
|
||||
logger.printTrace(javaVersionNotFound);
|
||||
|
@ -1360,6 +1360,7 @@ class EmulatorDomain extends Domain {
|
||||
EmulatorManager emulators = EmulatorManager(
|
||||
fileSystem: globals.fs,
|
||||
logger: globals.logger,
|
||||
java: globals.java,
|
||||
androidSdk: globals.androidSdk,
|
||||
processManager: globals.processManager,
|
||||
androidWorkflow: androidWorkflow!,
|
||||
|
@ -14,6 +14,7 @@ import 'android/android_studio.dart';
|
||||
import 'android/android_workflow.dart';
|
||||
import 'android/gradle.dart';
|
||||
import 'android/gradle_utils.dart';
|
||||
import 'android/java.dart';
|
||||
import 'application_package.dart';
|
||||
import 'artifacts.dart';
|
||||
import 'asset.dart';
|
||||
@ -97,11 +98,11 @@ Future<T> runInContext<T>(
|
||||
androidStudio: globals.androidStudio,
|
||||
),
|
||||
AndroidLicenseValidator: () => AndroidLicenseValidator(
|
||||
operatingSystemUtils: globals.os,
|
||||
platform: globals.platform,
|
||||
userMessages: globals.userMessages,
|
||||
processManager: globals.processManager,
|
||||
androidStudio: globals.androidStudio,
|
||||
java: globals.java,
|
||||
androidSdk: globals.androidSdk,
|
||||
logger: globals.logger,
|
||||
fileSystem: globals.fs,
|
||||
@ -216,6 +217,7 @@ Future<T> runInContext<T>(
|
||||
Doctor: () => Doctor(logger: globals.logger),
|
||||
DoctorValidatorsProvider: () => DoctorValidatorsProvider.defaultInstance,
|
||||
EmulatorManager: () => EmulatorManager(
|
||||
java: globals.java,
|
||||
androidSdk: globals.androidSdk,
|
||||
processManager: globals.processManager,
|
||||
logger: globals.logger,
|
||||
@ -253,6 +255,13 @@ Future<T> runInContext<T>(
|
||||
xcode: globals.xcode!,
|
||||
platform: globals.platform,
|
||||
),
|
||||
Java: () => Java.find(
|
||||
androidStudio: globals.androidStudio,
|
||||
logger: globals.logger,
|
||||
fileSystem: globals.fs,
|
||||
platform: globals.platform,
|
||||
processManager: globals.processManager
|
||||
),
|
||||
LocalEngineLocator: () => LocalEngineLocator(
|
||||
userMessages: userMessages,
|
||||
logger: globals.logger,
|
||||
|
@ -10,6 +10,7 @@ import 'package:process/process.dart';
|
||||
import 'android/android_emulator.dart';
|
||||
import 'android/android_sdk.dart';
|
||||
import 'android/android_workflow.dart';
|
||||
import 'android/java.dart';
|
||||
import 'base/context.dart';
|
||||
import 'base/file_system.dart';
|
||||
import 'base/logger.dart';
|
||||
@ -22,12 +23,14 @@ EmulatorManager? get emulatorManager => context.get<EmulatorManager>();
|
||||
/// A class to get all available emulators.
|
||||
class EmulatorManager {
|
||||
EmulatorManager({
|
||||
required Java? java,
|
||||
AndroidSdk? androidSdk,
|
||||
required Logger logger,
|
||||
required ProcessManager processManager,
|
||||
required AndroidWorkflow androidWorkflow,
|
||||
required FileSystem fileSystem,
|
||||
}) : _androidSdk = androidSdk,
|
||||
}) : _java = java,
|
||||
_androidSdk = androidSdk,
|
||||
_processUtils = ProcessUtils(logger: logger, processManager: processManager),
|
||||
_androidEmulators = AndroidEmulators(
|
||||
androidSdk: androidSdk,
|
||||
@ -39,6 +42,7 @@ class EmulatorManager {
|
||||
_emulatorDiscoverers.add(_androidEmulators);
|
||||
}
|
||||
|
||||
final Java? _java;
|
||||
final AndroidSdk? _androidSdk;
|
||||
final AndroidEmulators _androidEmulators;
|
||||
final ProcessUtils _processUtils;
|
||||
@ -152,7 +156,7 @@ class EmulatorManager {
|
||||
'-n', emulatorName,
|
||||
'-k', sdkId,
|
||||
'-d', device,
|
||||
], environment: _androidSdk?.sdkManagerEnv,
|
||||
], environment: _java?.environment,
|
||||
);
|
||||
return CreateEmulatorResult(
|
||||
emulatorName,
|
||||
@ -175,7 +179,7 @@ class EmulatorManager {
|
||||
'-c',
|
||||
];
|
||||
final RunResult runResult = await _processUtils.run(args,
|
||||
environment: _androidSdk?.sdkManagerEnv);
|
||||
environment: _java?.environment);
|
||||
if (runResult.exitCode != 0) {
|
||||
return null;
|
||||
}
|
||||
@ -205,7 +209,7 @@ class EmulatorManager {
|
||||
'-n', 'temp',
|
||||
];
|
||||
final RunResult runResult = await _processUtils.run(args,
|
||||
environment: _androidSdk?.sdkManagerEnv);
|
||||
environment: _java?.environment);
|
||||
|
||||
// Get the list of IDs that match our criteria
|
||||
final List<String> availableIDs = runResult.stderr
|
||||
|
@ -9,6 +9,7 @@ import 'package:unified_analytics/unified_analytics.dart';
|
||||
import 'android/android_sdk.dart';
|
||||
import 'android/android_studio.dart';
|
||||
import 'android/gradle_utils.dart';
|
||||
import 'android/java.dart';
|
||||
import 'artifacts.dart';
|
||||
import 'base/bot_detector.dart';
|
||||
import 'base/config.dart';
|
||||
@ -308,3 +309,9 @@ final RegExp kVMServiceMessageRegExp = RegExp(r'The Dart VM service is listening
|
||||
// The official tool no longer allows non-null safe builds. This can be
|
||||
// overridden in other clients.
|
||||
NonNullSafeBuilds get nonNullSafeBuilds => context.get<NonNullSafeBuilds>() ?? NonNullSafeBuilds.notAllowed;
|
||||
|
||||
/// Contains information about the JRE/JDK to use for Java-dependent operations.
|
||||
///
|
||||
/// A value of [null] indicates that no installation of java could be found on
|
||||
/// the host machine.
|
||||
Java? get java => context.get<Java>();
|
||||
|
@ -568,13 +568,7 @@ class AndroidProject extends FlutterProjectPlatform {
|
||||
hostAppGradleRoot, globals.logger, globals.processManager);
|
||||
final String? agpVersion =
|
||||
gradle.getAgpVersion(hostAppGradleRoot, globals.logger);
|
||||
final String? javaVersion = globals.androidSdk?.getJavaVersion(
|
||||
androidStudio: globals.androidStudio,
|
||||
fileSystem: globals.fs,
|
||||
operatingSystemUtils: globals.os,
|
||||
platform: globals.platform,
|
||||
processUtils: globals.processUtils,
|
||||
);
|
||||
final String? javaVersion = globals.java?.version?.number;
|
||||
|
||||
// Assume valid configuration.
|
||||
String description = validJavaGradleAgpString;
|
||||
|
@ -6,6 +6,7 @@ import 'dart:async';
|
||||
|
||||
import 'package:file/memory.dart';
|
||||
import 'package:flutter_tools/src/android/android_device.dart';
|
||||
import 'package:flutter_tools/src/android/java.dart';
|
||||
import 'package:flutter_tools/src/application_package.dart';
|
||||
import 'package:flutter_tools/src/base/file_system.dart';
|
||||
import 'package:flutter_tools/src/base/logger.dart';
|
||||
@ -20,6 +21,7 @@ import 'package:test/fake.dart';
|
||||
import '../../src/common.dart';
|
||||
import '../../src/context.dart';
|
||||
import '../../src/fake_devices.dart';
|
||||
import '../../src/fakes.dart';
|
||||
|
||||
void main() {
|
||||
Daemon? daemon;
|
||||
@ -104,6 +106,8 @@ void main() {
|
||||
final bool supportsRuntimeMode = await device.supportsRuntimeMode(BuildMode.release);
|
||||
expect(fakeDevice.supportsRuntimeModeCalledBuildMode, BuildMode.release);
|
||||
expect(supportsRuntimeMode, true);
|
||||
}, overrides: <Type, Generator>{
|
||||
Java: () => FakeJava(),
|
||||
});
|
||||
|
||||
testUsingContext('redirects logs', () async {
|
||||
@ -183,6 +187,7 @@ void main() {
|
||||
expect(fakeDevice.stopAppPackage, applicationPackage);
|
||||
expect(stopAppResult, true);
|
||||
}, overrides: <Type, Generator>{
|
||||
Java: () => FakeJava(),
|
||||
ApplicationPackageFactory: () => applicationPackageFactory,
|
||||
FileSystem: () => memoryFileSystem,
|
||||
ProcessManager: () => fakeProcessManager,
|
||||
@ -212,6 +217,7 @@ void main() {
|
||||
|
||||
expect(await screenshotOutputFile.readAsBytes(), screenshot);
|
||||
}, overrides: <Type, Generator>{
|
||||
Java: () => FakeJava(),
|
||||
FileSystem: () => memoryFileSystem,
|
||||
ProcessManager: () => fakeProcessManager,
|
||||
});
|
||||
|
@ -447,9 +447,6 @@ class FakeAndroidSdk extends Fake implements AndroidSdk {
|
||||
|
||||
@override
|
||||
final Directory directory;
|
||||
|
||||
@override
|
||||
String? get javaHome => 'java';
|
||||
}
|
||||
|
||||
class FakeAndroidStudio extends Fake implements AndroidStudio {
|
||||
|
@ -230,7 +230,4 @@ class FakeAndroidSdk extends Fake implements AndroidSdk {
|
||||
|
||||
@override
|
||||
final Directory directory;
|
||||
|
||||
@override
|
||||
String? get javaHome => 'java';
|
||||
}
|
||||
|
@ -389,8 +389,6 @@ class FakeDoctor extends Fake implements Doctor {
|
||||
}
|
||||
}
|
||||
|
||||
class FakeAndroidStudio extends Fake implements AndroidStudio {}
|
||||
|
||||
class FakeClock extends Fake implements SystemClock {
|
||||
List<int> times = <int>[];
|
||||
|
||||
|
@ -4,9 +4,9 @@
|
||||
|
||||
import 'package:file/file.dart';
|
||||
import 'package:file/memory.dart';
|
||||
import 'package:flutter_tools/src/android/android_sdk.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/java.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/base/logger.dart';
|
||||
@ -19,6 +19,7 @@ import 'package:test/fake.dart';
|
||||
|
||||
import '../../src/common.dart';
|
||||
import '../../src/context.dart';
|
||||
import '../../src/fakes.dart';
|
||||
|
||||
const String otherGradleVersionWrapper = r'''
|
||||
distributionBase=GRADLE_USER_HOME
|
||||
@ -46,6 +47,9 @@ zipStorePath=wrapper/dists
|
||||
|
||||
final Version androidStudioDolphin = Version(2021, 3, 1);
|
||||
|
||||
final JavaVersion _javaVersion17 = JavaVersion(longText: 'openjdk 17.0.2', number: '17.0.2');
|
||||
final JavaVersion _javaVersion16 = JavaVersion(longText: 'openjdk 16.0.2', number: '16.0.2');
|
||||
|
||||
void main() {
|
||||
group('Android migration', () {
|
||||
group('migrate the Gradle "clean" task to lazy declaration', () {
|
||||
@ -136,14 +140,10 @@ tasks.register("clean", Delete) {
|
||||
|
||||
testWithoutContext('skipped if files are missing', () {
|
||||
final AndroidStudioJavaGradleConflictMigration migration = AndroidStudioJavaGradleConflictMigration(
|
||||
java: FakeJava(version: _javaVersion17),
|
||||
bufferLogger,
|
||||
project: project,
|
||||
androidStudio: FakeAndroidStudio(version: androidStudioDolphin),
|
||||
fileSystem: FakeFileSystem(),
|
||||
processUtils: FakeProcessUtils(),
|
||||
platform: FakePlatform(),
|
||||
os: FakeOperatingSystemUtils(),
|
||||
androidSdk: FakeAndroidSdk(javaVersion: '17'),
|
||||
);
|
||||
migration.migrate();
|
||||
expect(gradleWrapperPropertiesFile.existsSync(), isFalse);
|
||||
@ -153,13 +153,9 @@ tasks.register("clean", Delete) {
|
||||
|
||||
testWithoutContext('skipped if android studio is null', () {
|
||||
final AndroidStudioJavaGradleConflictMigration migration = AndroidStudioJavaGradleConflictMigration(
|
||||
java: FakeJava(version: _javaVersion17),
|
||||
bufferLogger,
|
||||
project: project,
|
||||
fileSystem: FakeFileSystem(),
|
||||
processUtils: FakeProcessUtils(),
|
||||
platform: FakePlatform(),
|
||||
os: FakeOperatingSystemUtils(),
|
||||
androidSdk: FakeAndroidSdk(javaVersion: '17'),
|
||||
);
|
||||
gradleWrapperPropertiesFile.writeAsStringSync(gradleWrapperToMigrate);
|
||||
migration.migrate();
|
||||
@ -170,14 +166,10 @@ tasks.register("clean", Delete) {
|
||||
|
||||
testWithoutContext('skipped if android studio version is null', () {
|
||||
final AndroidStudioJavaGradleConflictMigration migration = AndroidStudioJavaGradleConflictMigration(
|
||||
java: FakeJava(version: _javaVersion17),
|
||||
bufferLogger,
|
||||
project: project,
|
||||
androidStudio: FakeAndroidStudio(version: null),
|
||||
fileSystem: FakeFileSystem(),
|
||||
processUtils: FakeProcessUtils(),
|
||||
platform: FakePlatform(),
|
||||
os: FakeOperatingSystemUtils(),
|
||||
androidSdk: FakeAndroidSdk(javaVersion: '17'),
|
||||
);
|
||||
gradleWrapperPropertiesFile.writeAsStringSync(gradleWrapperToMigrate);
|
||||
migration.migrate();
|
||||
@ -188,14 +180,10 @@ tasks.register("clean", Delete) {
|
||||
|
||||
testWithoutContext('skipped if error is encountered in migrate()', () {
|
||||
final AndroidStudioJavaGradleConflictMigration migration = AndroidStudioJavaGradleConflictMigration(
|
||||
java: FakeErroringJava(),
|
||||
bufferLogger,
|
||||
project: project,
|
||||
androidStudio: FakeAndroidStudio(version: androidStudioFlamingo),
|
||||
fileSystem: FakeFileSystem(),
|
||||
processUtils: FakeProcessUtils(),
|
||||
platform: FakePlatform(),
|
||||
os: FakeOperatingSystemUtils(),
|
||||
androidSdk: FakeErroringAndroidSdk(),
|
||||
);
|
||||
gradleWrapperPropertiesFile.writeAsStringSync(gradleWrapperToMigrate);
|
||||
migration.migrate();
|
||||
@ -206,14 +194,10 @@ tasks.register("clean", Delete) {
|
||||
|
||||
testWithoutContext('skipped if android studio version is less than flamingo', () {
|
||||
final AndroidStudioJavaGradleConflictMigration migration = AndroidStudioJavaGradleConflictMigration(
|
||||
java: FakeJava(),
|
||||
bufferLogger,
|
||||
project: project,
|
||||
androidStudio: FakeAndroidStudio(version: androidStudioDolphin),
|
||||
fileSystem: FakeFileSystem(),
|
||||
processUtils: FakeProcessUtils(),
|
||||
platform: FakePlatform(),
|
||||
os: FakeOperatingSystemUtils(),
|
||||
androidSdk: FakeAndroidSdk(javaVersion: '17'),
|
||||
);
|
||||
gradleWrapperPropertiesFile.writeAsStringSync(gradleWrapperToMigrate);
|
||||
migration.migrate();
|
||||
@ -223,14 +207,10 @@ tasks.register("clean", Delete) {
|
||||
|
||||
testWithoutContext('skipped if bundled java version is less than 17', () {
|
||||
final AndroidStudioJavaGradleConflictMigration migration = AndroidStudioJavaGradleConflictMigration(
|
||||
java: FakeJava(version: _javaVersion16),
|
||||
bufferLogger,
|
||||
project: project,
|
||||
androidStudio: FakeAndroidStudio(version: androidStudioFlamingo),
|
||||
fileSystem: FakeFileSystem(),
|
||||
processUtils: FakeProcessUtils(),
|
||||
platform: FakePlatform(),
|
||||
os: FakeOperatingSystemUtils(),
|
||||
androidSdk: FakeAndroidSdk(javaVersion: '16'),
|
||||
);
|
||||
gradleWrapperPropertiesFile.writeAsStringSync(gradleWrapperToMigrate);
|
||||
migration.migrate();
|
||||
@ -241,14 +221,10 @@ tasks.register("clean", Delete) {
|
||||
testWithoutContext('nothing is changed if gradle version not one that was '
|
||||
'used by flutter create', () {
|
||||
final AndroidStudioJavaGradleConflictMigration migration = AndroidStudioJavaGradleConflictMigration(
|
||||
java: FakeJava(version: _javaVersion17),
|
||||
bufferLogger,
|
||||
project: project,
|
||||
androidStudio: FakeAndroidStudio(version: androidStudioFlamingo),
|
||||
fileSystem: FakeFileSystem(),
|
||||
processUtils: FakeProcessUtils(),
|
||||
platform: FakePlatform(),
|
||||
os: FakeOperatingSystemUtils(),
|
||||
androidSdk: FakeAndroidSdk(javaVersion: '17'),
|
||||
);
|
||||
gradleWrapperPropertiesFile.writeAsStringSync(otherGradleVersionWrapper);
|
||||
migration.migrate();
|
||||
@ -259,14 +235,10 @@ tasks.register("clean", Delete) {
|
||||
testWithoutContext('change is made with one of the specific gradle versions'
|
||||
' we migrate for', () {
|
||||
final AndroidStudioJavaGradleConflictMigration migration = AndroidStudioJavaGradleConflictMigration(
|
||||
java: FakeJava(version: _javaVersion17),
|
||||
bufferLogger,
|
||||
project: project,
|
||||
androidStudio: FakeAndroidStudio(version: androidStudioFlamingo),
|
||||
fileSystem: FakeFileSystem(),
|
||||
processUtils: FakeProcessUtils(),
|
||||
platform: FakePlatform(),
|
||||
os: FakeOperatingSystemUtils(),
|
||||
androidSdk: FakeAndroidSdk(javaVersion: '17'),
|
||||
);
|
||||
gradleWrapperPropertiesFile.writeAsStringSync(gradleWrapperToMigrate);
|
||||
migration.migrate();
|
||||
@ -278,14 +250,10 @@ tasks.register("clean", Delete) {
|
||||
|
||||
testWithoutContext('change is not made when opt out flag is set', () {
|
||||
final AndroidStudioJavaGradleConflictMigration migration = AndroidStudioJavaGradleConflictMigration(
|
||||
java: FakeJava(version: _javaVersion17),
|
||||
bufferLogger,
|
||||
project: project,
|
||||
androidStudio: FakeAndroidStudio(version: androidStudioFlamingo),
|
||||
fileSystem: FakeFileSystem(),
|
||||
processUtils: FakeProcessUtils(),
|
||||
platform: FakePlatform(),
|
||||
os: FakeOperatingSystemUtils(),
|
||||
androidSdk: FakeAndroidSdk(javaVersion: '17'),
|
||||
);
|
||||
gradleWrapperPropertiesFile.writeAsStringSync(gradleWrapperToMigrate + optOutFlag);
|
||||
migration.migrate();
|
||||
@ -314,37 +282,10 @@ class FakeAndroidStudio extends Fake implements AndroidStudio {
|
||||
Version? get version => _version;
|
||||
}
|
||||
|
||||
class FakeAndroidSdk extends Fake implements AndroidSdk {
|
||||
FakeAndroidSdk({required String javaVersion}) {
|
||||
_javaVersion = javaVersion;
|
||||
}
|
||||
|
||||
late String _javaVersion;
|
||||
|
||||
class FakeErroringJava extends FakeJava {
|
||||
@override
|
||||
String? getJavaVersion({
|
||||
required AndroidStudio? androidStudio,
|
||||
required FileSystem fileSystem,
|
||||
required OperatingSystemUtils operatingSystemUtils,
|
||||
required Platform platform,
|
||||
required ProcessUtils processUtils,
|
||||
}) {
|
||||
return _javaVersion;
|
||||
}
|
||||
}
|
||||
|
||||
class FakeErroringAndroidSdk extends Fake implements AndroidSdk {
|
||||
FakeErroringAndroidSdk();
|
||||
|
||||
@override
|
||||
String? getJavaVersion({
|
||||
required AndroidStudio? androidStudio,
|
||||
required FileSystem fileSystem,
|
||||
required OperatingSystemUtils operatingSystemUtils,
|
||||
required Platform platform,
|
||||
required ProcessUtils processUtils,
|
||||
}) {
|
||||
throw const FileSystemException();
|
||||
JavaVersion get version {
|
||||
throw Exception('How did this happen?');
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -5,19 +5,16 @@
|
||||
import 'package:file/memory.dart';
|
||||
import 'package:flutter_tools/src/android/android_sdk.dart';
|
||||
import 'package:flutter_tools/src/android/android_studio.dart';
|
||||
import 'package:flutter_tools/src/android/java.dart';
|
||||
import 'package:flutter_tools/src/base/config.dart';
|
||||
import 'package:flutter_tools/src/base/file_system.dart';
|
||||
import 'package:flutter_tools/src/base/logger.dart';
|
||||
import 'package:flutter_tools/src/base/os.dart';
|
||||
import 'package:flutter_tools/src/base/platform.dart';
|
||||
import 'package:flutter_tools/src/base/process.dart';
|
||||
import 'package:flutter_tools/src/globals.dart' as globals;
|
||||
import 'package:test/fake.dart';
|
||||
|
||||
import '../../integration.shard/test_utils.dart';
|
||||
import '../../src/common.dart';
|
||||
import '../../src/context.dart';
|
||||
import '../../src/fakes.dart' show FakeAndroidStudio, FakeOperatingSystemUtils;
|
||||
|
||||
void main() {
|
||||
late MemoryFileSystem fileSystem;
|
||||
@ -354,18 +351,18 @@ void main() {
|
||||
final String androidStudioBundledJdkHome = globals.androidStudio!.javaPath!;
|
||||
final String expectedJavaBinaryPath = globals.fs.path.join(androidStudioBundledJdkHome, 'bin', 'java');
|
||||
|
||||
final String? foundJavaBinaryPath = AndroidSdk.findJavaBinary(
|
||||
final String? foundJavaBinaryPath = Java.find(
|
||||
logger: globals.logger,
|
||||
androidStudio: globals.androidStudio,
|
||||
fileSystem: globals.fs,
|
||||
operatingSystemUtils: globals.os,
|
||||
platform: globals.platform,
|
||||
);
|
||||
processManager: globals.processManager,
|
||||
)?.binaryPath;
|
||||
|
||||
expect(foundJavaBinaryPath, expectedJavaBinaryPath);
|
||||
}, overrides: <Type, Generator>{
|
||||
FileSystem: () => MemoryFileSystem.test(),
|
||||
ProcessManager: () => FakeProcessManager.any(),
|
||||
OperatingSystemUtils: () => FakeOperatingSystemUtilsWithJava(),
|
||||
Platform: () => FakePlatform(),
|
||||
Config: () => Config,
|
||||
AndroidStudio: () => FakeAndroidStudioWithJdk(),
|
||||
@ -374,18 +371,18 @@ void main() {
|
||||
testUsingContext('returns the current value of JAVA_HOME if it is set and the JDK bundled with Android Studio could not be found', () {
|
||||
final String expectedJavaBinaryPath = globals.fs.path.join('java-home-path', 'bin', 'java');
|
||||
|
||||
final String? foundJavaBinaryPath = AndroidSdk.findJavaBinary(
|
||||
final String? foundJavaBinaryPath = Java.find(
|
||||
logger: globals.logger,
|
||||
androidStudio: globals.androidStudio,
|
||||
fileSystem: globals.fs,
|
||||
operatingSystemUtils: globals.os,
|
||||
platform: globals.platform,
|
||||
);
|
||||
processManager: globals.processManager,
|
||||
)?.binaryPath;
|
||||
|
||||
expect(foundJavaBinaryPath, expectedJavaBinaryPath);
|
||||
}, overrides: <Type, Generator>{
|
||||
FileSystem: () => MemoryFileSystem.test(),
|
||||
ProcessManager: () => FakeProcessManager.any(),
|
||||
OperatingSystemUtils: () => FakeOperatingSystemUtilsWithJava(),
|
||||
ProcessManager: () => FakeProcessManager.empty(),
|
||||
Platform: () => FakePlatform(environment: <String, String>{
|
||||
AndroidSdk.javaHomeEnvironmentVariable: 'java-home-path',
|
||||
}),
|
||||
@ -394,168 +391,54 @@ void main() {
|
||||
});
|
||||
|
||||
testUsingContext('returns the java binary found on PATH if no other can be found', () {
|
||||
final String? foundJavaBinaryPath = AndroidSdk.findJavaBinary(
|
||||
final String? foundJavaBinaryPath = Java.find(
|
||||
logger: globals.logger,
|
||||
androidStudio: globals.androidStudio,
|
||||
fileSystem: globals.fs,
|
||||
operatingSystemUtils: globals.os,
|
||||
platform: globals.platform,
|
||||
);
|
||||
processManager: globals.processManager,
|
||||
)?.binaryPath;
|
||||
|
||||
expect(foundJavaBinaryPath, globals.os.which('java')!.path);
|
||||
expect(foundJavaBinaryPath, 'java');
|
||||
}, overrides: <Type, Generator>{
|
||||
Logger: () => BufferLogger.test(),
|
||||
FileSystem: () => MemoryFileSystem.test(),
|
||||
ProcessManager: () => FakeProcessManager.any(),
|
||||
OperatingSystemUtils: () => FakeOperatingSystemUtilsWithJava(),
|
||||
ProcessManager: () => FakeProcessManager.list(<FakeCommand>[
|
||||
const FakeCommand(
|
||||
command: <String>['which', 'java'],
|
||||
stdout: 'java',
|
||||
),
|
||||
]),
|
||||
Platform: () => FakePlatform(),
|
||||
Config: () => Config,
|
||||
AndroidStudio: () => FakeAndroidStudioWithoutJdk(),
|
||||
});
|
||||
|
||||
testUsingContext('returns null if no java binary could be found', () {
|
||||
final String? foundJavaBinaryPath = AndroidSdk.findJavaBinary(
|
||||
final String? foundJavaBinaryPath = Java.find(
|
||||
logger: globals.logger,
|
||||
androidStudio: globals.androidStudio,
|
||||
fileSystem: globals.fs,
|
||||
operatingSystemUtils: globals.os,
|
||||
platform: globals.platform,
|
||||
);
|
||||
processManager: globals.processManager,
|
||||
)?.binaryPath;
|
||||
|
||||
expect(foundJavaBinaryPath, null);
|
||||
}, overrides: <Type, Generator>{
|
||||
Logger: () => BufferLogger.test(),
|
||||
FileSystem: () => MemoryFileSystem.test(),
|
||||
ProcessManager: () => FakeProcessManager.any(),
|
||||
OperatingSystemUtils: () => FakeOperatingSystemUtilsWithoutJava(),
|
||||
ProcessManager: () => FakeProcessManager.list(<FakeCommand>[
|
||||
const FakeCommand(
|
||||
command: <String>['which', 'java'],
|
||||
exitCode: 1,
|
||||
),
|
||||
]),
|
||||
Platform: () => FakePlatform(),
|
||||
Config: () => Config,
|
||||
AndroidStudio: () => FakeAndroidStudioWithoutJdk(),
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
group('java version', () {
|
||||
const String exampleJdk8Output = '''
|
||||
java version "1.8.0_202"
|
||||
Java(TM) SE Runtime Environment (build 1.8.0_202-b10)
|
||||
Java HotSpot(TM) 64-Bit Server VM (build 25.202-b10, mixed mode)
|
||||
''';
|
||||
// Example strings came from actual terminal output.
|
||||
testWithoutContext('parses jdk 8', () {
|
||||
expect(AndroidSdk.parseJavaVersion(exampleJdk8Output), '1.8.0');
|
||||
});
|
||||
|
||||
testWithoutContext('parses jdk 11 windows', () {
|
||||
const String exampleJdkOutput = '''
|
||||
java version "11.0.14"
|
||||
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)
|
||||
''';
|
||||
expect(AndroidSdk.parseJavaVersion(exampleJdkOutput), '11.0.14');
|
||||
});
|
||||
|
||||
testWithoutContext('parses jdk 11 mac/linux', () {
|
||||
const String exampleJdkOutput = '''
|
||||
openjdk version "11.0.18" 2023-01-17 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)
|
||||
''';
|
||||
expect(AndroidSdk.parseJavaVersion(exampleJdkOutput), '11.0.18');
|
||||
});
|
||||
|
||||
testWithoutContext('parses jdk 17', () {
|
||||
const String exampleJdkOutput = '''
|
||||
openjdk 17.0.6 2023-01-17
|
||||
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)
|
||||
''';
|
||||
expect(AndroidSdk.parseJavaVersion(exampleJdkOutput), '17.0.6');
|
||||
});
|
||||
|
||||
testWithoutContext('parses jdk 19', () {
|
||||
const String exampleJdkOutput = '''
|
||||
openjdk 19.0.2 2023-01-17
|
||||
OpenJDK Runtime Environment Homebrew (build 19.0.2)
|
||||
OpenJDK 64-Bit Server VM Homebrew (build 19.0.2, mixed mode, sharing)
|
||||
''';
|
||||
expect(AndroidSdk.parseJavaVersion(exampleJdkOutput), '19.0.2');
|
||||
});
|
||||
|
||||
// https://chrome-infra-packages.appspot.com/p/flutter/java/openjdk/
|
||||
testWithoutContext('parses jdk output from ci', () {
|
||||
const String exampleJdkOutput = '''
|
||||
openjdk 11.0.2 2019-01-15
|
||||
OpenJDK Runtime Environment 18.9 (build 11.0.2+9)
|
||||
OpenJDK 64-Bit Server VM 18.9 (build 11.0.2+9, mixed mode)
|
||||
''';
|
||||
expect(AndroidSdk.parseJavaVersion(exampleJdkOutput), '11.0.2');
|
||||
});
|
||||
|
||||
testWithoutContext('parses jdk two number versions', () {
|
||||
const String exampleJdkOutput = 'openjdk 19.0 2023-01-17';
|
||||
expect(AndroidSdk.parseJavaVersion(exampleJdkOutput), '19.0');
|
||||
});
|
||||
|
||||
testUsingContext('getJavaBinary with AS install', () {
|
||||
final Directory sdkDir = createSdkDirectory(fileSystem: fileSystem);
|
||||
config.setValue('android-sdk', sdkDir.path);
|
||||
final AndroidStudio androidStudio = FakeAndroidStudio();
|
||||
|
||||
final String javaPath = AndroidSdk.findJavaBinary(
|
||||
androidStudio: androidStudio,
|
||||
fileSystem: fileSystem,
|
||||
operatingSystemUtils: FakeOperatingSystemUtils(),
|
||||
platform: platform)!;
|
||||
// Built from the implementation of findJavaBinary android studio case.
|
||||
final String expectedJavaPath = '${androidStudio.javaPath}/bin/java';
|
||||
|
||||
expect(javaPath, expectedJavaPath);
|
||||
}, overrides: <Type, Generator>{
|
||||
FileSystem: () => fileSystem,
|
||||
ProcessManager: () => processManager,
|
||||
Config: () => config,
|
||||
Platform: () => FakePlatform(environment: <String, String>{}),
|
||||
});
|
||||
|
||||
group('java', () {
|
||||
late AndroidStudio androidStudio;
|
||||
setUp(() {
|
||||
androidStudio = FakeAndroidStudio();
|
||||
});
|
||||
testUsingContext('getJavaVersion finds AS java and parses version', () {
|
||||
final Directory sdkDir = createSdkDirectory(fileSystem: fileSystem);
|
||||
config.setValue('android-sdk', sdkDir.path);
|
||||
|
||||
final ProcessUtils processUtils = ProcessUtils(
|
||||
processManager: processManager, logger: BufferLogger.test());
|
||||
// Built from the implementation of findJavaBinary android studio case.
|
||||
final String expectedJavaPath = '${androidStudio.javaPath}/bin/java';
|
||||
|
||||
processManager.addCommand(FakeCommand(
|
||||
command: <String>[
|
||||
expectedJavaPath,
|
||||
'--version',
|
||||
],
|
||||
stdout: exampleJdk8Output,
|
||||
));
|
||||
|
||||
final AndroidSdk sdk = AndroidSdk.locateAndroidSdk()!;
|
||||
|
||||
final String? javaVersion = sdk.getJavaVersion(
|
||||
androidStudio: androidStudio,
|
||||
fileSystem: fileSystem,
|
||||
operatingSystemUtils: FakeOperatingSystemUtils(),
|
||||
platform: FakePlatform(),
|
||||
processUtils: processUtils,
|
||||
);
|
||||
|
||||
expect(javaVersion, '1.8.0');
|
||||
}, overrides: <Type, Generator>{
|
||||
FileSystem: () => fileSystem,
|
||||
ProcessManager: () => processManager,
|
||||
AndroidStudio: () => androidStudio,
|
||||
Config: () => config,
|
||||
Platform: () => FakePlatform(environment: <String, String>{}),
|
||||
});
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
/// A broken SDK installation.
|
||||
@ -646,20 +529,3 @@ class FakeAndroidStudioWithoutJdk extends Fake implements AndroidStudio {
|
||||
@override
|
||||
String? get javaPath => null;
|
||||
}
|
||||
|
||||
class FakeOperatingSystemUtilsWithJava extends Fake implements OperatingSystemUtils {
|
||||
@override
|
||||
File? which(String execName) {
|
||||
if (execName == 'java') {
|
||||
return globals.fs.file('/fake/which/java/path');
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
class FakeOperatingSystemUtilsWithoutJava extends Fake implements OperatingSystemUtils {
|
||||
@override
|
||||
File? which(String execName) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
@ -122,6 +122,7 @@ void main() {
|
||||
sdk.sdkManagerPath = '/foo/bar/sdkmanager';
|
||||
processManager.excludedExecutables.add('/foo/bar/sdkmanager');
|
||||
final AndroidLicenseValidator licenseValidator = AndroidLicenseValidator(
|
||||
java: FakeJava(),
|
||||
androidSdk: sdk,
|
||||
fileSystem: fileSystem,
|
||||
processManager: processManager,
|
||||
@ -130,7 +131,6 @@ void main() {
|
||||
logger: BufferLogger.test(),
|
||||
userMessages: UserMessages(),
|
||||
androidStudio: FakeAndroidStudio(),
|
||||
operatingSystemUtils: FakeOperatingSystemUtils(),
|
||||
);
|
||||
final LicensesAccepted licenseStatus = await licenseValidator.licensesAccepted;
|
||||
|
||||
@ -141,6 +141,7 @@ void main() {
|
||||
sdk.sdkManagerPath = '/foo/bar/sdkmanager';
|
||||
processManager.excludedExecutables.add('/foo/bar/sdkmanager');
|
||||
final AndroidLicenseValidator licenseValidator = AndroidLicenseValidator(
|
||||
java: FakeJava(),
|
||||
androidSdk: sdk,
|
||||
fileSystem: fileSystem,
|
||||
processManager: processManager,
|
||||
@ -149,7 +150,6 @@ void main() {
|
||||
logger: BufferLogger.test(),
|
||||
userMessages: UserMessages(),
|
||||
androidStudio: FakeAndroidStudio(),
|
||||
operatingSystemUtils: FakeOperatingSystemUtils(),
|
||||
);
|
||||
final LicensesAccepted licenseStatus = await licenseValidator.licensesAccepted;
|
||||
|
||||
@ -165,6 +165,7 @@ void main() {
|
||||
], stdout: 'asdasassad',
|
||||
));
|
||||
final AndroidLicenseValidator licenseValidator = AndroidLicenseValidator(
|
||||
java: FakeJava(),
|
||||
androidSdk: sdk,
|
||||
fileSystem: fileSystem,
|
||||
processManager: processManager,
|
||||
@ -173,7 +174,6 @@ void main() {
|
||||
logger: BufferLogger.test(),
|
||||
userMessages: UserMessages(),
|
||||
androidStudio: FakeAndroidStudio(),
|
||||
operatingSystemUtils: FakeOperatingSystemUtils(),
|
||||
);
|
||||
final LicensesAccepted result = await licenseValidator.licensesAccepted;
|
||||
|
||||
@ -194,6 +194,7 @@ All SDK package licenses accepted.
|
||||
));
|
||||
|
||||
final AndroidLicenseValidator licenseValidator = AndroidLicenseValidator(
|
||||
java: FakeJava(),
|
||||
androidSdk: sdk,
|
||||
fileSystem: fileSystem,
|
||||
processManager: processManager,
|
||||
@ -202,7 +203,6 @@ All SDK package licenses accepted.
|
||||
logger: BufferLogger.test(),
|
||||
userMessages: UserMessages(),
|
||||
androidStudio: FakeAndroidStudio(),
|
||||
operatingSystemUtils: FakeOperatingSystemUtils(),
|
||||
);
|
||||
final LicensesAccepted result = await licenseValidator.licensesAccepted;
|
||||
|
||||
@ -224,6 +224,7 @@ Review licenses that have not been accepted (y/N)?
|
||||
));
|
||||
|
||||
final AndroidLicenseValidator licenseValidator = AndroidLicenseValidator(
|
||||
java: FakeJava(),
|
||||
androidSdk: sdk,
|
||||
fileSystem: fileSystem,
|
||||
processManager: processManager,
|
||||
@ -232,7 +233,6 @@ Review licenses that have not been accepted (y/N)?
|
||||
logger: BufferLogger.test(),
|
||||
userMessages: UserMessages(),
|
||||
androidStudio: FakeAndroidStudio(),
|
||||
operatingSystemUtils: FakeOperatingSystemUtils(),
|
||||
);
|
||||
final LicensesAccepted result = await licenseValidator.licensesAccepted;
|
||||
|
||||
@ -254,6 +254,7 @@ Review licenses that have not been accepted (y/N)?
|
||||
));
|
||||
|
||||
final AndroidLicenseValidator licenseValidator = AndroidLicenseValidator(
|
||||
java: FakeJava(),
|
||||
androidSdk: sdk,
|
||||
fileSystem: fileSystem,
|
||||
processManager: processManager,
|
||||
@ -262,7 +263,6 @@ Review licenses that have not been accepted (y/N)?
|
||||
logger: BufferLogger.test(),
|
||||
userMessages: UserMessages(),
|
||||
androidStudio: FakeAndroidStudio(),
|
||||
operatingSystemUtils: FakeOperatingSystemUtils(),
|
||||
);
|
||||
final LicensesAccepted result = await licenseValidator.licensesAccepted;
|
||||
|
||||
@ -280,6 +280,7 @@ Review licenses that have not been accepted (y/N)?
|
||||
));
|
||||
|
||||
final AndroidLicenseValidator licenseValidator = AndroidLicenseValidator(
|
||||
java: FakeJava(),
|
||||
androidSdk: sdk,
|
||||
fileSystem: fileSystem,
|
||||
processManager: processManager,
|
||||
@ -288,7 +289,6 @@ Review licenses that have not been accepted (y/N)?
|
||||
logger: BufferLogger.test(),
|
||||
userMessages: UserMessages(),
|
||||
androidStudio: FakeAndroidStudio(),
|
||||
operatingSystemUtils: FakeOperatingSystemUtils(),
|
||||
);
|
||||
|
||||
expect(await licenseValidator.runLicenseManager(), isTrue);
|
||||
@ -299,6 +299,7 @@ Review licenses that have not been accepted (y/N)?
|
||||
processManager.excludedExecutables.add('/foo/bar/sdkmanager');
|
||||
|
||||
final AndroidLicenseValidator licenseValidator = AndroidLicenseValidator(
|
||||
java: FakeJava(),
|
||||
androidSdk: sdk,
|
||||
fileSystem: fileSystem,
|
||||
processManager: processManager,
|
||||
@ -307,7 +308,6 @@ Review licenses that have not been accepted (y/N)?
|
||||
logger: BufferLogger.test(),
|
||||
userMessages: UserMessages(),
|
||||
androidStudio: FakeAndroidStudio(),
|
||||
operatingSystemUtils: FakeOperatingSystemUtils(),
|
||||
);
|
||||
|
||||
expect(licenseValidator.runLicenseManager(), throwsToolExit());
|
||||
@ -328,6 +328,7 @@ Review licenses that have not been accepted (y/N)?
|
||||
final BufferLogger logger = BufferLogger.test();
|
||||
|
||||
final AndroidLicenseValidator licenseValidator = AndroidLicenseValidator(
|
||||
java: FakeJava(),
|
||||
androidSdk: sdk,
|
||||
fileSystem: fileSystem,
|
||||
processManager: processManager,
|
||||
@ -336,7 +337,6 @@ Review licenses that have not been accepted (y/N)?
|
||||
logger: logger,
|
||||
userMessages: UserMessages(),
|
||||
androidStudio: FakeAndroidStudio(),
|
||||
operatingSystemUtils: FakeOperatingSystemUtils(),
|
||||
);
|
||||
|
||||
await licenseValidator.runLicenseManager();
|
||||
@ -349,6 +349,7 @@ Review licenses that have not been accepted (y/N)?
|
||||
processManager.excludedExecutables.add('/foo/bar/sdkmanager');
|
||||
|
||||
final AndroidLicenseValidator licenseValidator = AndroidLicenseValidator(
|
||||
java: FakeJava(),
|
||||
androidSdk: sdk,
|
||||
fileSystem: fileSystem,
|
||||
processManager: processManager,
|
||||
@ -357,7 +358,6 @@ Review licenses that have not been accepted (y/N)?
|
||||
logger: BufferLogger.test(),
|
||||
userMessages: UserMessages(),
|
||||
androidStudio: FakeAndroidStudio(),
|
||||
operatingSystemUtils: FakeOperatingSystemUtils(),
|
||||
);
|
||||
|
||||
expect(licenseValidator.runLicenseManager(), throwsToolExit());
|
||||
@ -376,6 +376,7 @@ Review licenses that have not been accepted (y/N)?
|
||||
);
|
||||
|
||||
final AndroidLicenseValidator licenseValidator = AndroidLicenseValidator(
|
||||
java: FakeJava(),
|
||||
androidSdk: sdk,
|
||||
fileSystem: fileSystem,
|
||||
processManager: processManager,
|
||||
@ -384,7 +385,6 @@ Review licenses that have not been accepted (y/N)?
|
||||
logger: logger,
|
||||
userMessages: UserMessages(),
|
||||
androidStudio: FakeAndroidStudio(),
|
||||
operatingSystemUtils: FakeOperatingSystemUtils(),
|
||||
);
|
||||
|
||||
await expectLater(
|
||||
@ -620,9 +620,6 @@ class FakeAndroidSdk extends Fake implements AndroidSdk {
|
||||
|
||||
@override
|
||||
List<String> validateSdkWellFormed() => <String>[];
|
||||
|
||||
@override
|
||||
Map<String, String> get sdkManagerEnv => <String, String>{};
|
||||
}
|
||||
|
||||
class FakeAndroidSdkVersion extends Fake implements AndroidSdkVersion {
|
||||
|
254
packages/flutter_tools/test/general.shard/android/java_test.dart
Normal file
254
packages/flutter_tools/test/general.shard/android/java_test.dart
Normal file
@ -0,0 +1,254 @@
|
||||
// Copyright 2014 The Flutter Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
import 'package:file/memory.dart';
|
||||
import 'package:flutter_tools/src/android/android_studio.dart';
|
||||
import 'package:flutter_tools/src/android/java.dart';
|
||||
import 'package:flutter_tools/src/base/file_system.dart';
|
||||
import 'package:flutter_tools/src/base/logger.dart';
|
||||
import 'package:flutter_tools/src/base/os.dart';
|
||||
import 'package:flutter_tools/src/base/platform.dart';
|
||||
import 'package:test/fake.dart';
|
||||
import 'package:webdriver/async_io.dart';
|
||||
|
||||
import '../../integration.shard/test_utils.dart';
|
||||
import '../../src/common.dart';
|
||||
import '../../src/context.dart';
|
||||
import '../../src/fakes.dart';
|
||||
|
||||
void main() {
|
||||
|
||||
late Logger logger;
|
||||
late FileSystem fs;
|
||||
late Platform platform;
|
||||
late FakeProcessManager processManager;
|
||||
|
||||
setUp(() {
|
||||
logger = BufferLogger.test();
|
||||
fs = MemoryFileSystem.test();
|
||||
platform = FakePlatform(environment: <String, String>{
|
||||
'PATH': '',
|
||||
});
|
||||
processManager = FakeProcessManager.empty();
|
||||
});
|
||||
|
||||
group(Java, () {
|
||||
|
||||
group('find', () {
|
||||
testWithoutContext('finds the JDK bundled with Android Studio, if it exists', () {
|
||||
final AndroidStudio androidStudio = _FakeAndroidStudioWithJdk();
|
||||
final String androidStudioBundledJdkHome = androidStudio.javaPath!;
|
||||
final String expectedJavaBinaryPath = fs.path.join(androidStudioBundledJdkHome, 'bin', 'java');
|
||||
|
||||
processManager.addCommand(FakeCommand(
|
||||
command: <String>[
|
||||
expectedJavaBinaryPath,
|
||||
'--version',
|
||||
],
|
||||
stdout: '''
|
||||
openjdk 19.0.2 2023-01-17
|
||||
OpenJDK Runtime Environment Zulu19.32+15-CA (build 19.0.2+7)
|
||||
OpenJDK 64-Bit Server VM Zulu19.32+15-CA (build 19.0.2+7, mixed mode, sharing)
|
||||
'''
|
||||
));
|
||||
final Java java = Java.find(
|
||||
androidStudio: androidStudio,
|
||||
logger: logger,
|
||||
fileSystem: fs,
|
||||
platform: platform,
|
||||
processManager: processManager,
|
||||
)!;
|
||||
final JavaVersion version = java.version!;
|
||||
|
||||
expect(java.javaHome, androidStudioBundledJdkHome);
|
||||
expect(java.binaryPath, expectedJavaBinaryPath);
|
||||
|
||||
expect(version.longText, 'OpenJDK Runtime Environment Zulu19.32+15-CA (build 19.0.2+7)');
|
||||
expect(version.number, '19.0.2');
|
||||
});
|
||||
|
||||
testWithoutContext('finds JAVA_HOME if it is set and the JDK bundled with Android Studio could not be found', () {
|
||||
final AndroidStudio androidStudio = _FakeAndroidStudioWithoutJdk();
|
||||
const String javaHome = '/java/home';
|
||||
final String expectedJavaBinaryPath = fs.path.join(javaHome, 'bin', 'java');
|
||||
|
||||
final Java java = Java.find(
|
||||
androidStudio: androidStudio,
|
||||
logger: logger,
|
||||
fileSystem: fs,
|
||||
platform: FakePlatform(environment: <String, String>{
|
||||
'JAVA_HOME': javaHome,
|
||||
}),
|
||||
processManager: processManager,
|
||||
)!;
|
||||
|
||||
expect(java.javaHome, javaHome);
|
||||
expect(java.binaryPath, expectedJavaBinaryPath);
|
||||
});
|
||||
|
||||
testWithoutContext('returns the java binary found on PATH if no other can be found', () {
|
||||
final AndroidStudio androidStudio = _FakeAndroidStudioWithoutJdk();
|
||||
final OperatingSystemUtils os = _FakeOperatingSystemUtilsWithJava(fileSystem);
|
||||
|
||||
processManager.addCommand(
|
||||
const FakeCommand(
|
||||
command: <String>['which', 'java'],
|
||||
stdout: '/fake/which/java/path',
|
||||
),
|
||||
);
|
||||
|
||||
final Java java = Java.find(
|
||||
androidStudio: androidStudio,
|
||||
logger: logger,
|
||||
fileSystem: fs,
|
||||
platform: platform,
|
||||
processManager: processManager,
|
||||
)!;
|
||||
|
||||
expect(java.binaryPath, os.which('java')!.path);
|
||||
expect(java.javaHome, isNull);
|
||||
});
|
||||
|
||||
testWithoutContext('returns null if no java could be found', () {
|
||||
final AndroidStudio androidStudio = _FakeAndroidStudioWithoutJdk();
|
||||
processManager.addCommand(
|
||||
const FakeCommand(
|
||||
command: <String>['which', 'java'],
|
||||
exitCode: 1,
|
||||
),
|
||||
);
|
||||
final Java? java = Java.find(
|
||||
androidStudio: androidStudio,
|
||||
logger: logger,
|
||||
fileSystem: fs,
|
||||
platform: platform,
|
||||
processManager: processManager,
|
||||
);
|
||||
expect(java, isNull);
|
||||
});
|
||||
});
|
||||
|
||||
group('getVersionString', () {
|
||||
late Java java;
|
||||
|
||||
setUp(() {
|
||||
processManager = FakeProcessManager.empty();
|
||||
java = Java(
|
||||
fileSystem: fs,
|
||||
logger: logger,
|
||||
os: FakeOperatingSystemUtils(),
|
||||
platform: platform,
|
||||
processManager: processManager,
|
||||
binaryPath: 'javaHome/bin/java',
|
||||
javaHome: 'javaHome',
|
||||
);
|
||||
});
|
||||
|
||||
void addJavaVersionCommand(String output) {
|
||||
processManager.addCommand(
|
||||
FakeCommand(
|
||||
command: <String>[java.binaryPath, '--version'],
|
||||
stdout: output,
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
testWithoutContext('parses jdk 8', () {
|
||||
addJavaVersionCommand('''
|
||||
java version "1.8.0_202"
|
||||
Java(TM) SE Runtime Environment (build 1.8.0_202-b10)
|
||||
Java HotSpot(TM) 64-Bit Server VM (build 25.202-b10, mixed mode)
|
||||
''');
|
||||
final JavaVersion version = java.version!;
|
||||
expect(version.longText, 'Java(TM) SE Runtime Environment (build 1.8.0_202-b10)');
|
||||
expect(version.number, '1.8.0');
|
||||
});
|
||||
testWithoutContext('parses jdk 11 windows', () {
|
||||
addJavaVersionCommand('''
|
||||
java version "11.0.14"
|
||||
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)
|
||||
''');
|
||||
final JavaVersion version = java.version!;
|
||||
expect(version.longText, 'Java(TM) SE Runtime Environment (build 11.0.14+10-b13)');
|
||||
expect(version.number, '11.0.14');
|
||||
});
|
||||
|
||||
testWithoutContext('parses jdk 11 mac/linux', () {
|
||||
addJavaVersionCommand('''
|
||||
openjdk version "11.0.18" 2023-01-17 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)
|
||||
''');
|
||||
final JavaVersion version = java.version!;
|
||||
expect(version.longText, 'OpenJDK Runtime Environment Zulu11.62+17-CA (build 11.0.18+10-LTS)');
|
||||
expect(version.number, '11.0.18');
|
||||
});
|
||||
|
||||
testWithoutContext('parses jdk 17', () {
|
||||
addJavaVersionCommand('''
|
||||
openjdk 17.0.6 2023-01-17
|
||||
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)
|
||||
''');
|
||||
final JavaVersion version = java.version!;
|
||||
expect(version.longText, 'OpenJDK Runtime Environment (build 17.0.6+0-17.0.6b802.4-9586694)');
|
||||
expect(version.number, '17.0.6');
|
||||
});
|
||||
|
||||
testWithoutContext('parses jdk 19', () {
|
||||
addJavaVersionCommand('''
|
||||
openjdk 19.0.2 2023-01-17
|
||||
OpenJDK Runtime Environment Homebrew (build 19.0.2)
|
||||
OpenJDK 64-Bit Server VM Homebrew (build 19.0.2, mixed mode, sharing)
|
||||
''');
|
||||
final JavaVersion version = java.version!;
|
||||
expect(version.longText, 'OpenJDK Runtime Environment Homebrew (build 19.0.2)');
|
||||
expect(version.number, '19.0.2');
|
||||
});
|
||||
|
||||
// https://chrome-infra-packages.appspot.com/p/flutter/java/openjdk/
|
||||
testWithoutContext('parses jdk output from ci', () {
|
||||
addJavaVersionCommand('''
|
||||
openjdk 11.0.2 2019-01-15
|
||||
OpenJDK Runtime Environment 18.9 (build 11.0.2+9)
|
||||
OpenJDK 64-Bit Server VM 18.9 (build 11.0.2+9, mixed mode)
|
||||
''');
|
||||
final JavaVersion version = java.version!;
|
||||
expect(version.longText, 'OpenJDK Runtime Environment 18.9 (build 11.0.2+9)');
|
||||
expect(version.number, '11.0.2');
|
||||
});
|
||||
|
||||
testWithoutContext('parses jdk two number versions', () {
|
||||
addJavaVersionCommand('openjdk 19.0 2023-01-17');
|
||||
final JavaVersion version = java.version!;
|
||||
expect(version.longText, 'openjdk 19.0 2023-01-17');
|
||||
expect(version.number, '19.0');
|
||||
});
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
class _FakeAndroidStudioWithJdk extends Fake implements AndroidStudio {
|
||||
@override
|
||||
String? get javaPath => '/fake/android_studio/java/path/';
|
||||
}
|
||||
|
||||
class _FakeAndroidStudioWithoutJdk extends Fake implements AndroidStudio {
|
||||
@override
|
||||
String? get javaPath => null;
|
||||
}
|
||||
|
||||
class _FakeOperatingSystemUtilsWithJava extends FakeOperatingSystemUtils {
|
||||
_FakeOperatingSystemUtilsWithJava(this._fileSystem);
|
||||
|
||||
final FileSystem _fileSystem;
|
||||
@override
|
||||
File? which(String execName) {
|
||||
if (execName == 'java') {
|
||||
return _fileSystem.file('/fake/which/java/path');
|
||||
}
|
||||
throw const InvalidArgumentException(null, null);
|
||||
}
|
||||
}
|
@ -67,6 +67,7 @@ void main() {
|
||||
testUsingContext('getEmulators', () async {
|
||||
// Test that EmulatorManager.getEmulators() doesn't throw.
|
||||
final EmulatorManager emulatorManager = EmulatorManager(
|
||||
java: FakeJava(),
|
||||
fileSystem: MemoryFileSystem.test(),
|
||||
logger: BufferLogger.test(),
|
||||
processManager: FakeProcessManager.list(<FakeCommand>[
|
||||
@ -89,6 +90,7 @@ void main() {
|
||||
testUsingContext('getEmulators with no Android SDK', () async {
|
||||
// Test that EmulatorManager.getEmulators() doesn't throw when there's no Android SDK.
|
||||
final EmulatorManager emulatorManager = EmulatorManager(
|
||||
java: FakeJava(),
|
||||
fileSystem: MemoryFileSystem.test(),
|
||||
logger: BufferLogger.test(),
|
||||
processManager: FakeProcessManager.list(<FakeCommand>[
|
||||
@ -109,6 +111,7 @@ void main() {
|
||||
|
||||
testWithoutContext('getEmulatorsById', () async {
|
||||
final TestEmulatorManager testEmulatorManager = TestEmulatorManager(emulators,
|
||||
java: FakeJava(),
|
||||
logger: BufferLogger.test(),
|
||||
processManager: fakeProcessManager,
|
||||
androidWorkflow: AndroidWorkflow(
|
||||
@ -129,6 +132,7 @@ void main() {
|
||||
testUsingContext('create emulator with a missing avdmanager does not crash.', () async {
|
||||
sdk.avdManagerPath = null;
|
||||
final EmulatorManager emulatorManager = EmulatorManager(
|
||||
java: FakeJava(),
|
||||
fileSystem: MemoryFileSystem.test(),
|
||||
logger: BufferLogger.test(),
|
||||
processManager: FakeProcessManager.list(<FakeCommand>[
|
||||
@ -152,6 +156,7 @@ void main() {
|
||||
// iOS discovery uses context.
|
||||
testUsingContext('create emulator with an empty name does not fail', () async {
|
||||
final EmulatorManager emulatorManager = EmulatorManager(
|
||||
java: FakeJava(),
|
||||
fileSystem: MemoryFileSystem.test(),
|
||||
logger: BufferLogger.test(),
|
||||
processManager: FakeProcessManager.list(<FakeCommand>[
|
||||
@ -191,6 +196,7 @@ void main() {
|
||||
|
||||
testWithoutContext('create emulator with a unique name does not throw', () async {
|
||||
final EmulatorManager emulatorManager = EmulatorManager(
|
||||
java: FakeJava(),
|
||||
fileSystem: MemoryFileSystem.test(),
|
||||
logger: BufferLogger.test(),
|
||||
processManager: FakeProcessManager.list(<FakeCommand>[
|
||||
@ -227,6 +233,7 @@ void main() {
|
||||
|
||||
testWithoutContext('create emulator with an existing name errors', () async {
|
||||
final EmulatorManager emulatorManager = EmulatorManager(
|
||||
java: FakeJava(),
|
||||
fileSystem: MemoryFileSystem.test(),
|
||||
logger: BufferLogger.test(),
|
||||
processManager: FakeProcessManager.list(<FakeCommand>[
|
||||
@ -266,6 +273,7 @@ void main() {
|
||||
// iOS discovery uses context.
|
||||
testUsingContext('create emulator without a name but when default exists adds a suffix', () async {
|
||||
final EmulatorManager emulatorManager = EmulatorManager(
|
||||
java: FakeJava(),
|
||||
fileSystem: MemoryFileSystem.test(),
|
||||
logger: BufferLogger.test(),
|
||||
processManager: FakeProcessManager.list(<FakeCommand>[
|
||||
@ -342,6 +350,7 @@ void main() {
|
||||
|
||||
class TestEmulatorManager extends EmulatorManager {
|
||||
TestEmulatorManager(this.allEmulators, {
|
||||
required super.java,
|
||||
required super.logger,
|
||||
required super.processManager,
|
||||
required super.androidWorkflow,
|
||||
@ -393,7 +402,4 @@ class FakeAndroidSdk extends Fake implements AndroidSdk {
|
||||
|
||||
@override
|
||||
String getAvdPath() => 'avd';
|
||||
|
||||
@override
|
||||
Map<String, String> get sdkManagerEnv => <String, String>{};
|
||||
}
|
||||
|
@ -7,11 +7,10 @@ import 'package:file/memory.dart';
|
||||
import 'package:flutter_tools/src/android/android_sdk.dart';
|
||||
import 'package:flutter_tools/src/android/android_studio.dart';
|
||||
import 'package:flutter_tools/src/android/gradle_utils.dart' as gradle_utils;
|
||||
import 'package:flutter_tools/src/android/java.dart';
|
||||
import 'package:flutter_tools/src/base/file_system.dart';
|
||||
import 'package:flutter_tools/src/base/logger.dart';
|
||||
import 'package:flutter_tools/src/base/os.dart';
|
||||
import 'package:flutter_tools/src/base/platform.dart';
|
||||
import 'package:flutter_tools/src/base/process.dart';
|
||||
import 'package:flutter_tools/src/build_info.dart';
|
||||
import 'package:flutter_tools/src/cache.dart';
|
||||
import 'package:flutter_tools/src/convert.dart';
|
||||
@ -407,9 +406,7 @@ void main() {
|
||||
});
|
||||
|
||||
group('java gradle agp compatibility', () {
|
||||
Future<FlutterProject?> configureJavaGradleAgpForTest(
|
||||
FakeAndroidSdkWithDir androidSdk, {
|
||||
required String javaV,
|
||||
Future<FlutterProject?> configureGradleAgpForTest({
|
||||
required String gradleV,
|
||||
required String agpV,
|
||||
}) async {
|
||||
@ -422,7 +419,6 @@ dependencies {
|
||||
''';
|
||||
});
|
||||
addGradleWrapperFile(project.directory, gradleV);
|
||||
androidSdk.javaVersion = javaV;
|
||||
return project;
|
||||
}
|
||||
|
||||
@ -431,22 +427,22 @@ dependencies {
|
||||
// especially important for filesystem.
|
||||
group('_', () {
|
||||
final FakeProcessManager processManager;
|
||||
final Java java;
|
||||
final AndroidStudio androidStudio;
|
||||
final FakeAndroidSdkWithDir androidSdk;
|
||||
final FileSystem fileSystem = getFileSystemForPlatform();
|
||||
java = FakeJava(version: JavaVersion(longText: '17.0.2', number: '17.0.2'));
|
||||
processManager = FakeProcessManager.empty();
|
||||
androidStudio = FakeAndroidStudio();
|
||||
androidSdk =
|
||||
FakeAndroidSdkWithDir(fileSystem.currentDirectory, androidStudio);
|
||||
FakeAndroidSdkWithDir(fileSystem.currentDirectory);
|
||||
fileSystem.currentDirectory
|
||||
.childDirectory(androidStudio.javaPath!)
|
||||
.createSync();
|
||||
_testInMemory(
|
||||
'flamingo values are compatible',
|
||||
() async {
|
||||
final FlutterProject? project = await configureJavaGradleAgpForTest(
|
||||
androidSdk,
|
||||
javaV: '17.0.2',
|
||||
final FlutterProject? project = await configureGradleAgpForTest(
|
||||
gradleV: '8.0',
|
||||
agpV: '7.4.2',
|
||||
);
|
||||
@ -454,6 +450,7 @@ dependencies {
|
||||
await project!.android.hasValidJavaGradleAgpVersions();
|
||||
expect(value.success, isTrue);
|
||||
},
|
||||
java: java,
|
||||
androidStudio: androidStudio,
|
||||
processManager: processManager,
|
||||
androidSdk: androidSdk,
|
||||
@ -461,22 +458,22 @@ dependencies {
|
||||
});
|
||||
group('_', () {
|
||||
final FakeProcessManager processManager;
|
||||
final Java java;
|
||||
final AndroidStudio androidStudio;
|
||||
final FakeAndroidSdkWithDir androidSdk;
|
||||
final FileSystem fileSystem = getFileSystemForPlatform();
|
||||
java = FakeJava(version: JavaVersion(longText: '1.8.0_242', number: '1.8.0_242'));
|
||||
processManager = FakeProcessManager.empty();
|
||||
androidStudio = FakeAndroidStudio();
|
||||
androidSdk =
|
||||
FakeAndroidSdkWithDir(fileSystem.currentDirectory, androidStudio);
|
||||
FakeAndroidSdkWithDir(fileSystem.currentDirectory);
|
||||
fileSystem.currentDirectory
|
||||
.childDirectory(androidStudio.javaPath!)
|
||||
.createSync();
|
||||
_testInMemory(
|
||||
'java 8 era values are compatible',
|
||||
() async {
|
||||
final FlutterProject? project = await configureJavaGradleAgpForTest(
|
||||
androidSdk,
|
||||
javaV: '1.8.0_242',
|
||||
final FlutterProject? project = await configureGradleAgpForTest(
|
||||
gradleV: '6.7.1',
|
||||
agpV: '4.2.0',
|
||||
);
|
||||
@ -484,6 +481,7 @@ dependencies {
|
||||
await project!.android.hasValidJavaGradleAgpVersions();
|
||||
expect(value.success, isTrue);
|
||||
},
|
||||
java: java,
|
||||
androidStudio: androidStudio,
|
||||
processManager: processManager,
|
||||
androidSdk: androidSdk,
|
||||
@ -492,22 +490,22 @@ dependencies {
|
||||
|
||||
group('_', () {
|
||||
final FakeProcessManager processManager;
|
||||
final Java java;
|
||||
final AndroidStudio androidStudio;
|
||||
final FakeAndroidSdkWithDir androidSdk;
|
||||
final FileSystem fileSystem = getFileSystemForPlatform();
|
||||
processManager = FakeProcessManager.empty();
|
||||
java = FakeJava(version: JavaVersion(longText: '11.0.14', number: '11.0.14'));
|
||||
androidStudio = FakeAndroidStudio();
|
||||
androidSdk =
|
||||
FakeAndroidSdkWithDir(fileSystem.currentDirectory, androidStudio);
|
||||
FakeAndroidSdkWithDir(fileSystem.currentDirectory);
|
||||
fileSystem.currentDirectory
|
||||
.childDirectory(androidStudio.javaPath!)
|
||||
.createSync();
|
||||
_testInMemory(
|
||||
'electric eel era values are compatible',
|
||||
() async {
|
||||
final FlutterProject? project = await configureJavaGradleAgpForTest(
|
||||
androidSdk,
|
||||
javaV: '11.0.14',
|
||||
final FlutterProject? project = await configureGradleAgpForTest(
|
||||
gradleV: '7.3.3',
|
||||
agpV: '7.2.0',
|
||||
);
|
||||
@ -515,32 +513,35 @@ dependencies {
|
||||
await project!.android.hasValidJavaGradleAgpVersions();
|
||||
expect(value.success, isTrue);
|
||||
},
|
||||
java: java,
|
||||
androidStudio: androidStudio,
|
||||
processManager: processManager,
|
||||
androidSdk: androidSdk,
|
||||
);
|
||||
});
|
||||
group('_', () {
|
||||
const String javaV = '17.0.2';
|
||||
const String gradleV = '6.7.3';
|
||||
const String agpV = '7.2.0';
|
||||
|
||||
final FakeProcessManager processManager;
|
||||
final Java java;
|
||||
final AndroidStudio androidStudio;
|
||||
final FakeAndroidSdkWithDir androidSdk;
|
||||
final FileSystem fileSystem = getFileSystemForPlatform();
|
||||
processManager = FakeProcessManager.empty();
|
||||
java = FakeJava(version: JavaVersion(longText: javaV, number: javaV));
|
||||
androidStudio = FakeAndroidStudio();
|
||||
androidSdk =
|
||||
FakeAndroidSdkWithDir(fileSystem.currentDirectory, androidStudio);
|
||||
FakeAndroidSdkWithDir(fileSystem.currentDirectory);
|
||||
fileSystem.currentDirectory
|
||||
.childDirectory(androidStudio.javaPath!)
|
||||
.createSync();
|
||||
_testInMemory(
|
||||
'incompatible everything',
|
||||
() async {
|
||||
const String javaV = '17.0.2';
|
||||
const String gradleV = '6.7.3';
|
||||
const String agpV = '7.2.0';
|
||||
final FlutterProject? project = await configureJavaGradleAgpForTest(
|
||||
androidSdk,
|
||||
javaV: javaV,
|
||||
|
||||
final FlutterProject? project = await configureGradleAgpForTest(
|
||||
gradleV: gradleV,
|
||||
agpV: agpV,
|
||||
);
|
||||
@ -563,32 +564,34 @@ dependencies {
|
||||
expect(value.description, contains(RegExp(javaV)));
|
||||
expect(value.description, contains(RegExp(gradleV)));
|
||||
},
|
||||
java: java,
|
||||
androidStudio: androidStudio,
|
||||
processManager: processManager,
|
||||
androidSdk: androidSdk,
|
||||
);
|
||||
});
|
||||
group('_', () {
|
||||
const String javaV = '17.0.2';
|
||||
const String gradleV = '6.7.3';
|
||||
const String agpV = '4.2.0';
|
||||
|
||||
final FakeProcessManager processManager;
|
||||
final Java java;
|
||||
final AndroidStudio androidStudio;
|
||||
final FakeAndroidSdkWithDir androidSdk;
|
||||
final FileSystem fileSystem = getFileSystemForPlatform();
|
||||
processManager = FakeProcessManager.empty();
|
||||
java = FakeJava(version: JavaVersion(longText: '17.0.2', number: '17.0.2'));
|
||||
androidStudio = FakeAndroidStudio();
|
||||
androidSdk =
|
||||
FakeAndroidSdkWithDir(fileSystem.currentDirectory, androidStudio);
|
||||
FakeAndroidSdkWithDir(fileSystem.currentDirectory);
|
||||
fileSystem.currentDirectory
|
||||
.childDirectory(androidStudio.javaPath!)
|
||||
.createSync();
|
||||
_testInMemory(
|
||||
'incompatible java/gradle only',
|
||||
() async {
|
||||
const String javaV = '17.0.2';
|
||||
const String gradleV = '6.7.3';
|
||||
const String agpV = '4.2.0';
|
||||
final FlutterProject? project = await configureJavaGradleAgpForTest(
|
||||
androidSdk,
|
||||
javaV: javaV,
|
||||
final FlutterProject? project = await configureGradleAgpForTest(
|
||||
gradleV: gradleV,
|
||||
agpV: agpV,
|
||||
);
|
||||
@ -606,6 +609,7 @@ dependencies {
|
||||
expect(value.description, contains(RegExp(javaV)));
|
||||
expect(value.description, contains(RegExp(gradleV)));
|
||||
},
|
||||
java: java,
|
||||
androidStudio: androidStudio,
|
||||
processManager: processManager,
|
||||
androidSdk: androidSdk,
|
||||
@ -613,25 +617,24 @@ dependencies {
|
||||
});
|
||||
group('_', () {
|
||||
final FakeProcessManager processManager;
|
||||
final Java java;
|
||||
final AndroidStudio androidStudio;
|
||||
final FakeAndroidSdkWithDir androidSdk;
|
||||
final FileSystem fileSystem = getFileSystemForPlatform();
|
||||
java = FakeJava(version: JavaVersion(longText: '11.0.2', number: '11.0.2'));
|
||||
processManager = FakeProcessManager.empty();
|
||||
androidStudio = FakeAndroidStudio();
|
||||
androidSdk =
|
||||
FakeAndroidSdkWithDir(fileSystem.currentDirectory, androidStudio);
|
||||
FakeAndroidSdkWithDir(fileSystem.currentDirectory);
|
||||
fileSystem.currentDirectory
|
||||
.childDirectory(androidStudio.javaPath!)
|
||||
.createSync();
|
||||
_testInMemory(
|
||||
'incompatible gradle/agp only',
|
||||
() async {
|
||||
const String javaV = '11.0.2';
|
||||
const String gradleV = '7.0.3';
|
||||
const String agpV = '7.1.0';
|
||||
final FlutterProject? project = await configureJavaGradleAgpForTest(
|
||||
androidSdk,
|
||||
javaV: javaV,
|
||||
final FlutterProject? project = await configureGradleAgpForTest(
|
||||
gradleV: gradleV,
|
||||
agpV: agpV,
|
||||
);
|
||||
@ -649,6 +652,7 @@ dependencies {
|
||||
expect(value.description, contains(RegExp(gradleV)));
|
||||
expect(value.description, contains(RegExp(agpV)));
|
||||
},
|
||||
java: java,
|
||||
androidStudio: androidStudio,
|
||||
processManager: processManager,
|
||||
androidSdk: androidSdk,
|
||||
@ -1404,6 +1408,7 @@ void _testInMemory(
|
||||
String description,
|
||||
Future<void> Function() testMethod, {
|
||||
FileSystem? fileSystem,
|
||||
Java? java,
|
||||
AndroidStudio? androidStudio,
|
||||
ProcessManager? processManager,
|
||||
AndroidSdk? androidSdk,
|
||||
@ -1466,6 +1471,7 @@ void _testInMemory(
|
||||
overrides: <Type, Generator>{
|
||||
FileSystem: () => testFileSystem,
|
||||
ProcessManager: () => processManager ?? FakeProcessManager.any(),
|
||||
Java : () => java,
|
||||
AndroidStudio: () => androidStudio ?? FakeAndroidStudio(),
|
||||
// Intentionlly null if not set. Some ios tests fail if this is a fake.
|
||||
AndroidSdk: () => androidSdk,
|
||||
@ -1667,37 +1673,10 @@ class FakeXcodeProjectInterpreter extends Fake implements XcodeProjectInterprete
|
||||
}
|
||||
|
||||
class FakeAndroidSdkWithDir extends Fake implements AndroidSdk {
|
||||
FakeAndroidSdkWithDir(this._directory, AndroidStudio _androidStudio) {
|
||||
_javaPath = '${_androidStudio.javaPath}/bin/java';
|
||||
}
|
||||
late String _javaPath;
|
||||
String? javaVersion;
|
||||
FakeAndroidSdkWithDir(this._directory);
|
||||
|
||||
final Directory _directory;
|
||||
|
||||
@override
|
||||
late bool platformToolsAvailable;
|
||||
|
||||
@override
|
||||
late bool licensesAvailable;
|
||||
|
||||
@override
|
||||
AndroidSdkVersion? latestVersion;
|
||||
|
||||
@override
|
||||
Directory get directory => _directory;
|
||||
|
||||
@override
|
||||
Map<String, String> get sdkManagerEnv => <String, String>{'PATH': _javaPath};
|
||||
|
||||
@override
|
||||
String? getJavaVersion({
|
||||
required AndroidStudio? androidStudio,
|
||||
required FileSystem fileSystem,
|
||||
required OperatingSystemUtils operatingSystemUtils,
|
||||
required Platform platform,
|
||||
required ProcessUtils processUtils,
|
||||
}) {
|
||||
return javaVersion;
|
||||
}
|
||||
}
|
||||
|
@ -7,6 +7,7 @@ import 'dart:io' as io show IOSink, ProcessSignal, Stdout, StdoutException;
|
||||
|
||||
import 'package:flutter_tools/src/android/android_sdk.dart';
|
||||
import 'package:flutter_tools/src/android/android_studio.dart';
|
||||
import 'package:flutter_tools/src/android/java.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/io.dart';
|
||||
@ -588,6 +589,7 @@ class FakeFlutterProjectFactory implements FlutterProjectFactory {
|
||||
}
|
||||
|
||||
class FakeAndroidSdk extends Fake implements AndroidSdk {
|
||||
|
||||
@override
|
||||
late bool platformToolsAvailable;
|
||||
|
||||
@ -602,3 +604,41 @@ class FakeAndroidStudio extends Fake implements AndroidStudio {
|
||||
@override
|
||||
String get javaPath => 'java';
|
||||
}
|
||||
|
||||
class FakeJava extends Fake implements Java {
|
||||
FakeJava({
|
||||
this.javaHome = '/android-studio/jbr',
|
||||
String binary = '/android-studio/jbr/bin/java',
|
||||
JavaVersion? version,
|
||||
bool canRun = true,
|
||||
}): binaryPath = binary,
|
||||
version = version ?? JavaVersion(
|
||||
longText: 'openjdk 19.0.2 2023-01-17',
|
||||
number: '19.0.2',
|
||||
),
|
||||
_environment = <String, String>{
|
||||
if (javaHome != null) 'JAVA_HOME': javaHome,
|
||||
'PATH': '/android-studio/jbr/bin',
|
||||
},
|
||||
_canRun = canRun;
|
||||
|
||||
@override
|
||||
String? javaHome;
|
||||
|
||||
@override
|
||||
String binaryPath;
|
||||
|
||||
final Map<String, String> _environment;
|
||||
final bool _canRun;
|
||||
|
||||
@override
|
||||
Map<String, String> get environment => _environment;
|
||||
|
||||
@override
|
||||
JavaVersion? version;
|
||||
|
||||
@override
|
||||
bool canRun() {
|
||||
return _canRun;
|
||||
}
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user