diff --git a/packages/flutter_tools/lib/src/android/android_emulator.dart b/packages/flutter_tools/lib/src/android/android_emulator.dart index 2c387ee144..43a0edda00 100644 --- a/packages/flutter_tools/lib/src/android/android_emulator.dart +++ b/packages/flutter_tools/lib/src/android/android_emulator.dart @@ -56,7 +56,7 @@ class AndroidEmulators extends EmulatorDiscovery { /// Return the list of available emulator AVDs. Future> _getEmulatorAvds() async { - final String emulatorPath = getEmulatorPath(_androidSdk); + final String emulatorPath = _androidSdk.emulatorPath; if (emulatorPath == null) { return []; } @@ -81,7 +81,7 @@ class AndroidEmulators extends EmulatorDiscovery { AndroidEmulator _loadEmulatorInfo(String id) { id = id.trim(); - final String avdPath = getAvdPath(); + final String avdPath = _androidSdk.getAvdPath(); final AndroidEmulator androidEmulatorWithoutProperties = AndroidEmulator( id, processManager: _processManager, @@ -150,7 +150,7 @@ class AndroidEmulator extends Emulator { @override Future launch() async { final Process process = await _processUtils.start( - [getEmulatorPath(_androidSdk), '-avd', id], + [_androidSdk.emulatorPath, '-avd', id], ); // Record output from the emulator process. diff --git a/packages/flutter_tools/lib/src/android/android_sdk.dart b/packages/flutter_tools/lib/src/android/android_sdk.dart index 1179eba66a..a48801a197 100644 --- a/packages/flutter_tools/lib/src/android/android_sdk.dart +++ b/packages/flutter_tools/lib/src/android/android_sdk.dart @@ -19,6 +19,26 @@ import 'android_studio.dart'; const String kAndroidHome = 'ANDROID_HOME'; const String kAndroidSdkRoot = 'ANDROID_SDK_ROOT'; +final RegExp _numberedAndroidPlatformRe = RegExp(r'^android-([0-9]+)$'); +final RegExp _sdkVersionRe = RegExp(r'^ro.build.version.sdk=([0-9]+)$'); + +/// The minimum Android SDK version we support. +const int minimumAndroidSdkVersion = 25; + +/// Locate ADB. Prefer to use one from an Android SDK, if we can locate that. +/// This should be used over accessing androidSdk.adbPath directly because it +/// will work for those users who have Android Platform Tools installed but +/// not the full SDK. +String getAdbPath(AndroidSdk existingSdk) { + if (existingSdk?.adbPath != null) { + return existingSdk.adbPath; + } + if (existingSdk?.latestVersion == null) { + return globals.os.which('adb')?.path; + } + return existingSdk?.adbPath; +} + // Android SDK layout: // $ANDROID_SDK_ROOT/platform-tools/adb @@ -32,77 +52,6 @@ const String kAndroidSdkRoot = 'ANDROID_SDK_ROOT'; // $ANDROID_SDK_ROOT/platforms/android-22/android.jar // $ANDROID_SDK_ROOT/platforms/android-23/android.jar // $ANDROID_SDK_ROOT/platforms/android-N/android.jar - -final RegExp _numberedAndroidPlatformRe = RegExp(r'^android-([0-9]+)$'); -final RegExp _sdkVersionRe = RegExp(r'^ro.build.version.sdk=([0-9]+)$'); - -/// The minimum Android SDK version we support. -const int minimumAndroidSdkVersion = 25; - -/// Locate ADB. Prefer to use one from an Android SDK, if we can locate that. -/// This should be used over accessing androidSdk.adbPath directly because it -/// will work for those users who have Android Platform Tools installed but -/// not the full SDK. -String getAdbPath([ AndroidSdk existingSdk ]) { - if (existingSdk?.adbPath != null) { - return existingSdk.adbPath; - } - - final AndroidSdk sdk = AndroidSdk.locateAndroidSdk(); - - if (sdk?.latestVersion == null) { - return globals.os.which('adb')?.path; - } else { - return sdk?.adbPath; - } -} - -/// Locate 'emulator'. Prefer to use one from an Android SDK, if we can locate that. -/// This should be used over accessing androidSdk.emulatorPath directly because it -/// will work for those users who have Android Tools installed but -/// not the full SDK. -String getEmulatorPath([ AndroidSdk existingSdk ]) { - return existingSdk?.emulatorPath ?? - AndroidSdk.locateAndroidSdk()?.emulatorPath; -} - -/// Locate the path for storing AVD emulator images. Returns null if none found. -String getAvdPath() { - - final List searchPaths = [ - globals.platform.environment['ANDROID_AVD_HOME'], - if (globals.platform.environment['HOME'] != null) - globals.fs.path.join(globals.platform.environment['HOME'], '.android', 'avd'), - ]; - - - if (globals.platform.isWindows) { - final String homeDrive = globals.platform.environment['HOMEDRIVE']; - final String homePath = globals.platform.environment['HOMEPATH']; - - if (homeDrive != null && homePath != null) { - // Can't use path.join for HOMEDRIVE/HOMEPATH - // https://github.com/dart-lang/path/issues/37 - final String home = homeDrive + homePath; - searchPaths.add(globals.fs.path.join(home, '.android', 'avd')); - } - } - - return searchPaths.where((String p) => p != null).firstWhere( - (String p) => globals.fs.directory(p).existsSync(), - orElse: () => null, - ); -} - -/// Locate 'avdmanager'. Prefer to use one from an Android SDK, if we can locate that. -/// This should be used over accessing androidSdk.avdManagerPath directly because it -/// will work for those users who have Android Tools installed but -/// not the full SDK. -String getAvdManagerPath([ AndroidSdk existingSdk ]) { - return existingSdk?.avdManagerPath ?? - AndroidSdk.locateAndroidSdk()?.avdManagerPath; -} - class AndroidSdk { AndroidSdk(this.directory) { reinitialize(); @@ -240,6 +189,32 @@ class AndroidSdk { String get avdManagerPath => getAvdManagerPath(); + /// Locate the path for storing AVD emulator images. Returns null if none found. + String getAvdPath() { + final List searchPaths = [ + globals.platform.environment['ANDROID_AVD_HOME'], + if (globals.platform.environment['HOME'] != null) + globals.fs.path.join(globals.platform.environment['HOME'], '.android', 'avd'), + ]; + + if (globals.platform.isWindows) { + final String homeDrive = globals.platform.environment['HOMEDRIVE']; + final String homePath = globals.platform.environment['HOMEPATH']; + + if (homeDrive != null && homePath != null) { + // Can't use path.join for HOMEDRIVE/HOMEPATH + // https://github.com/dart-lang/path/issues/37 + final String home = homeDrive + homePath; + searchPaths.add(globals.fs.path.join(home, '.android', 'avd')); + } + } + + return searchPaths.where((String p) => p != null).firstWhere( + (String p) => globals.fs.directory(p).existsSync(), + orElse: () => null, + ); + } + Directory get _platformsDir => globals.fs.directory(globals.fs.path.join(directory, 'platforms')); Iterable get _platforms { diff --git a/packages/flutter_tools/lib/src/android/android_workflow.dart b/packages/flutter_tools/lib/src/android/android_workflow.dart index 556ab2c5f0..5c2e1af82c 100644 --- a/packages/flutter_tools/lib/src/android/android_workflow.dart +++ b/packages/flutter_tools/lib/src/android/android_workflow.dart @@ -64,7 +64,7 @@ class AndroidWorkflow implements Workflow { bool get canLaunchDevices => _androidSdk != null && _androidSdk.validateSdkWellFormed().isEmpty; @override - bool get canListEmulators => getEmulatorPath(_androidSdk) != null; + bool get canListEmulators => _androidSdk.emulatorPath != null; } class AndroidValidator extends DoctorValidator { diff --git a/packages/flutter_tools/lib/src/emulator.dart b/packages/flutter_tools/lib/src/emulator.dart index c788dc72c3..d560a65adc 100644 --- a/packages/flutter_tools/lib/src/emulator.dart +++ b/packages/flutter_tools/lib/src/emulator.dart @@ -140,7 +140,7 @@ class EmulatorManager { .trim(); } final RunResult runResult = await _processUtils.run([ - getAvdManagerPath(_androidSdk), + _androidSdk?.avdManagerPath, 'create', 'avd', '-n', name, @@ -163,7 +163,7 @@ class EmulatorManager { Future _getPreferredAvailableDevice() async { final List args = [ - getAvdManagerPath(_androidSdk), + _androidSdk?.avdManagerPath, 'list', 'device', '-c', @@ -191,7 +191,7 @@ class EmulatorManager { // It seems that to get the available list of images, we need to send a // request to create without the image and it'll provide us a list :-( final List args = [ - getAvdManagerPath(_androidSdk), + _androidSdk?.avdManagerPath, 'create', 'avd', '-n', 'temp', diff --git a/packages/flutter_tools/test/general.shard/android/android_emulator_test.dart b/packages/flutter_tools/test/general.shard/android/android_emulator_test.dart index a89788d6c6..82a1b108c4 100644 --- a/packages/flutter_tools/test/general.shard/android/android_emulator_test.dart +++ b/packages/flutter_tools/test/general.shard/android/android_emulator_test.dart @@ -4,8 +4,6 @@ import 'dart:async'; -import 'package:flutter_tools/src/android/android_sdk.dart' - show getEmulatorPath; import 'package:flutter_tools/src/android/android_emulator.dart'; import 'package:flutter_tools/src/base/common.dart'; import 'package:flutter_tools/src/base/logger.dart'; @@ -144,8 +142,6 @@ void main() { logger: BufferLogger.test(), ); - expect(getEmulatorPath(mockSdk), mockSdk.emulatorPath); - final Completer completer = Completer(); FakeAsync().run((FakeAsync time) { unawaited(emulator.launch().whenComplete(completer.complete));