diff --git a/packages/flutter_tools/lib/src/android/adb.dart b/packages/flutter_tools/lib/src/android/adb.dart index 377bca83806..0320b3c152a 100644 --- a/packages/flutter_tools/lib/src/android/adb.dart +++ b/packages/flutter_tools/lib/src/android/adb.dart @@ -234,6 +234,8 @@ class AdbDevice { } } +final RegExp _whitespaceRegex = new RegExp(r'\s+'); + String cleanAdbDeviceName(String name) { // Some emulators use `___` in the name as separators. name = name.replaceAll('___', ', '); @@ -241,6 +243,8 @@ String cleanAdbDeviceName(String name) { // Convert `Nexus_7` / `Nexus_5X` style names to `Nexus 7` ones. name = name.replaceAll('_', ' '); + name = name.replaceAll(_whitespaceRegex, ' ').trim(); + return name; } diff --git a/packages/flutter_tools/lib/src/android/android_device.dart b/packages/flutter_tools/lib/src/android/android_device.dart index 2252b6e589b..4d54600f37d 100644 --- a/packages/flutter_tools/lib/src/android/android_device.dart +++ b/packages/flutter_tools/lib/src/android/android_device.dart @@ -207,6 +207,7 @@ class AndroidDevice extends Device { this.clearLogs(); runCheckedSync(adbCommandForDevice(['push', bundlePath, _deviceBundlePath])); + List cmd = adbCommandForDevice([ 'shell', 'am', 'start', '-a', 'android.intent.action.RUN', @@ -270,10 +271,9 @@ class AndroidDevice extends Device { } } - Future stopApp(ApplicationPackage app) async { - final AndroidApk apk = app; - runSync(adbCommandForDevice(['shell', 'am', 'force-stop', apk.id])); - return true; + Future stopApp(ApplicationPackage app) { + List command = adbCommandForDevice(['shell', 'am', 'force-stop', app.id]); + return runCommandAndStreamOutput(command).then((int exitCode) => exitCode == 0); } @override diff --git a/packages/flutter_tools/lib/src/commands/apk.dart b/packages/flutter_tools/lib/src/commands/apk.dart index ac190de6ba7..3a96b6dceed 100644 --- a/packages/flutter_tools/lib/src/commands/apk.dart +++ b/packages/flutter_tools/lib/src/commands/apk.dart @@ -349,16 +349,20 @@ bool _needsRebuild(String apkPath, String manifest) { Iterable dependenciesStat = [ manifest, _kFlutterManifestPath, - _kPackagesStatusPath, - '$apkPath.sha1' + _kPackagesStatusPath ].map((String path) => FileStat.statSync(path)); if (apkStat.type == FileSystemEntityType.NOT_FOUND) return true; + for (FileStat dep in dependenciesStat) { if (dep.modified == null || dep.modified.isAfter(apkStat.modified)) return true; } + + if (!FileSystemEntity.isFileSync('$apkPath.sha1')) + return true; + return false; } diff --git a/packages/flutter_tools/lib/src/commands/run.dart b/packages/flutter_tools/lib/src/commands/run.dart index 55d8bee5e43..918ef71cabb 100644 --- a/packages/flutter_tools/lib/src/commands/run.dart +++ b/packages/flutter_tools/lib/src/commands/run.dart @@ -19,7 +19,6 @@ import '../toolchain.dart'; import 'apk.dart'; import 'devices.dart'; import 'install.dart'; -import 'stop.dart'; /// Given the value of the --target option, return the path of the Dart file /// where the app's main function should be. @@ -65,7 +64,7 @@ class RunCommand extends RunCommandBase { RunCommand() { argParser.addFlag('full-restart', - defaultsTo: false, + defaultsTo: true, help: 'Stop any currently running application process before starting the app.'); argParser.addFlag('clear-logs', defaultsTo: true, @@ -111,6 +110,7 @@ class RunCommand extends RunCommandBase { return 1; } + // TODO(devoncarew): Switch this to using [devicesForCommand]. int result = await startApp( devices, applicationPackages, @@ -140,7 +140,7 @@ Future startApp( List configs, { String target, String enginePath, - bool stop: false, + bool stop: true, bool install: true, bool checked: true, bool traceStartup: false, @@ -169,11 +169,26 @@ Future startApp( return result; } + // TODO: Move this into the startApp() device impl. They should wait on the + // stop command to complete before (re-)starting the app. We could plumb a + // Future through the start command from here, but that seems a little messy. if (stop) { - printTrace('Running stop command.'); - await stopAll(devices, applicationPackages); + for (Device device in devices.all) { + if (!device.isSupported()) + continue; + + ApplicationPackage package = applicationPackages.getPackageForPlatform(device.platform); + if (package != null) { + printTrace("Stopping app '${package.name}' on ${device.name}."); + // We don't wait for the stop command to complete. + device.stopApp(package); + } + } } + // Allow any stop commands from above to start work. + await new Future.delayed(Duration.ZERO); + if (install) { printTrace('Running install command.'); // TODO(devoncarew): This fails for ios devices - we haven't built yet. @@ -194,8 +209,6 @@ Future startApp( continue; } - printTrace('Running build command for $device.'); - Map platformArgs = {}; if (traceStartup != null) @@ -223,9 +236,8 @@ Future startApp( // If the user specified --start-paused (and the device supports it) then // wait for the observatory port to become available before returning from // `startApp()`. - if (startPaused && device.supportsStartPaused) { + if (startPaused && device.supportsStartPaused) await delayUntilObservatoryAvailable('localhost', debugPort); - } } }