// 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:args/args.dart'; import '../base/common.dart'; import '../base/utils.dart'; import '../doctor_validator.dart'; import '../emulator.dart'; import '../globals.dart' as globals; import '../runner/flutter_command.dart'; class EmulatorsCommand extends FlutterCommand { EmulatorsCommand() { argParser.addOption('launch', help: 'The full or partial ID of the emulator to launch.'); argParser.addFlag('cold', help: 'Used with the "--launch" flag to cold boot the emulator instance (Android only).', negatable: false); argParser.addFlag('create', help: 'Creates a new Android emulator based on a Pixel device.', negatable: false); argParser.addOption('name', help: 'Used with the "--create" flag. Specifies a name for the emulator being created.'); } @override final String name = 'emulators'; @override final String description = 'List, launch and create emulators.'; @override final String category = FlutterCommandCategory.tools; @override final List<String> aliases = <String>['emulator']; @override Future<FlutterCommandResult> runCommand() async { if (globals.doctor!.workflows.every((Workflow w) => !w.canListEmulators)) { throwToolExit( 'Unable to find any emulator sources. Please ensure you have some\n' 'Android AVD images ${globals.platform.isMacOS ? 'or an iOS Simulator ' : ''}available.', exitCode: 1); } final ArgResults argumentResults = argResults!; if (argumentResults.wasParsed('launch')) { final bool coldBoot = argumentResults.wasParsed('cold'); await _launchEmulator(stringArgDeprecated('launch')!, coldBoot: coldBoot); } else if (argumentResults.wasParsed('create')) { await _createEmulator(name: stringArgDeprecated('name')); } else { final String? searchText = argumentResults.rest != null && argumentResults.rest.isNotEmpty ? argumentResults.rest.first : null; await _listEmulators(searchText); } return FlutterCommandResult.success(); } Future<void> _launchEmulator(String id, { required bool coldBoot }) async { final List<Emulator> emulators = await emulatorManager!.getEmulatorsMatching(id); if (emulators.isEmpty) { globals.printStatus("No emulator found that matches '$id'."); } else if (emulators.length > 1) { _printEmulatorList( emulators, "More than one emulator matches '$id':", ); } else { await emulators.first.launch(coldBoot: coldBoot); } } Future<void> _createEmulator({ String? name }) async { final CreateEmulatorResult createResult = await emulatorManager!.createEmulator(name: name); if (createResult.success) { globals.printStatus("Emulator '${createResult.emulatorName}' created successfully."); } else { globals.printStatus("Failed to create emulator '${createResult.emulatorName}'.\n"); final String? error = createResult.error; if (error != null) { globals.printStatus(error.trim()); } _printAdditionalInfo(); } } Future<void> _listEmulators(String? searchText) async { final List<Emulator> emulators = searchText == null ? await emulatorManager!.getAllAvailableEmulators() : await emulatorManager!.getEmulatorsMatching(searchText); if (emulators.isEmpty) { globals.printStatus('No emulators available.'); _printAdditionalInfo(showCreateInstruction: true); } else { _printEmulatorList( emulators, '${emulators.length} available ${pluralize('emulator', emulators.length)}:', ); } } void _printEmulatorList(List<Emulator> emulators, String message) { globals.printStatus('$message\n'); Emulator.printEmulators(emulators, globals.logger); _printAdditionalInfo(showCreateInstruction: true, showRunInstruction: true); } void _printAdditionalInfo({ bool showRunInstruction = false, bool showCreateInstruction = false, }) { globals.printStatus(''); if (showRunInstruction) { globals.printStatus( "To run an emulator, run 'flutter emulators --launch <emulator id>'."); } if (showCreateInstruction) { globals.printStatus( "To create a new emulator, run 'flutter emulators --create [--name xyz]'."); } if (showRunInstruction || showCreateInstruction) { globals.printStatus(''); } // TODO(dantup): Update this link to flutter.dev if/when we have a better page. // That page can then link out to these places if required. globals.printStatus('You can find more information on managing emulators at the links below:\n' ' https://developer.android.com/studio/run/managing-avds\n' ' https://developer.android.com/studio/command-line/avdmanager'); } }