Clean up 'flutter run' output. (#6610)
Fixes #4166.
Fixes #5120.
Fixes #5399.
Fixes #6507.
diff --git a/packages/flutter_tools/lib/src/android/android_device.dart b/packages/flutter_tools/lib/src/android/android_device.dart
index 8a84e6a..ab108ae 100644
--- a/packages/flutter_tools/lib/src/android/android_device.dart
+++ b/packages/flutter_tools/lib/src/android/android_device.dart
@@ -269,14 +269,16 @@
return true;
}
- Future<Null> _forwardPort(String service, int devicePort, int port) async {
+ Future<int> _forwardPort(String service, int devicePort, int port) async {
try {
// Set up port forwarding for observatory.
port = await portForwarder.forward(devicePort, hostPort: port);
- printStatus('$service listening on http://127.0.0.1:$port');
+ printTrace('$service listening on http://127.0.0.1:$port');
+ return port;
} catch (e) {
printError('Unable to forward port $port: $e');
}
+ return null;
}
Future<LaunchResult> startBundle(AndroidApk apk, String bundlePath, {
@@ -363,17 +365,17 @@
observatoryDevicePort = await observatoryDiscovery.nextPort().timeout(new Duration(seconds: 20));
}
- printTrace('observatory port = $observatoryDevicePort');
+ printTrace('observatory port on device: $observatoryDevicePort');
int observatoryLocalPort = await options.findBestObservatoryPort();
// TODO(devoncarew): Remember the forwarding information (so we can later remove the
// port forwarding).
- await _forwardPort(ProtocolDiscovery.kObservatoryService, observatoryDevicePort, observatoryLocalPort);
+ observatoryLocalPort = await _forwardPort(ProtocolDiscovery.kObservatoryService, observatoryDevicePort, observatoryLocalPort);
int diagnosticLocalPort;
if (diagnosticDevicePort != null) {
- printTrace('diagnostic port = $diagnosticDevicePort');
+ printTrace('diagnostic port on device: $diagnosticDevicePort');
diagnosticLocalPort = await options.findBestDiagnosticPort();
- await _forwardPort(ProtocolDiscovery.kDiagnosticService, diagnosticDevicePort, diagnosticLocalPort);
+ diagnosticLocalPort = await _forwardPort(ProtocolDiscovery.kDiagnosticService, diagnosticDevicePort, diagnosticLocalPort);
}
return new LaunchResult.succeeded(
@@ -715,8 +717,6 @@
final AndroidDevice device;
- bool _lastWasFiltered = false;
-
StreamController<String> _linesController;
Process _process;
@@ -757,38 +757,44 @@
}
// 'W/ActivityManager: '
- static final RegExp _logFormat = new RegExp(r'^[VDIWEF]\/[^:]+:\s+');
+ static final RegExp _logFormat = new RegExp(r'^[VDIWEF]\/.{8,}:\s');
static final List<RegExp> _whitelistedTags = <RegExp>[
new RegExp(r'^[VDIWEF]\/flutter[^:]*:\s+', caseSensitive: false),
new RegExp(r'^[IE]\/DartVM[^:]*:\s+'),
new RegExp(r'^[WEF]\/AndroidRuntime:\s+'),
- new RegExp(r'^[WEF]\/ActivityManager:\s+'),
+ new RegExp(r'^[WEF]\/ActivityManager:\s+.*(\bflutter\b|\bdomokit\b|\bsky\b)'),
new RegExp(r'^[WEF]\/System\.err:\s+'),
new RegExp(r'^[F]\/[\S^:]+:\s+')
];
+ // we default to true in case none of the log lines match
+ bool _acceptedLastLine = true;
+
void _onLine(String line) {
if (_logFormat.hasMatch(line)) {
- // Filter out some noisy ActivityManager notifications.
- if (line.startsWith('W/ActivityManager: getRunningAppProcesses'))
- return;
-
// Filter on approved names and levels.
for (RegExp regex in _whitelistedTags) {
if (regex.hasMatch(line)) {
- _lastWasFiltered = false;
+ _acceptedLastLine = true;
_linesController.add(line);
return;
}
}
-
- _lastWasFiltered = true;
+ _acceptedLastLine = false;
+ } else if (line == '--------- beginning of system' ||
+ line == '--------- beginning of main' ) {
+ // hide the ugly adb logcat log boundaries at the start
+ _acceptedLastLine = false;
} else {
- // If it doesn't match the log pattern at all, pass it through.
- if (!_lastWasFiltered)
+ // If it doesn't match the log pattern at all, then pass it through if we
+ // passed the last matching line through. It might be a multiline message.
+ if (_acceptedLastLine) {
_linesController.add(line);
+ return;
+ }
}
+ printTrace('skipped log line: $line');
}
void _stop() {
diff --git a/packages/flutter_tools/lib/src/commands/build_apk.dart b/packages/flutter_tools/lib/src/commands/build_apk.dart
index 6ac544b..6f0cec8 100644
--- a/packages/flutter_tools/lib/src/commands/build_apk.dart
+++ b/packages/flutter_tools/lib/src/commands/build_apk.dart
@@ -378,7 +378,7 @@
artifactBuilder.directory, components.resources, buildMode
);
- int signResult = _signApk(builder, components, unalignedApk, keystore);
+ int signResult = _signApk(builder, components, unalignedApk, keystore, buildMode);
if (signResult != 0)
return signResult;
@@ -397,7 +397,11 @@
}
int _signApk(
- _ApkBuilder builder, _ApkComponents components, File apk, ApkKeystoreInfo keystoreInfo
+ _ApkBuilder builder,
+ _ApkComponents components,
+ File apk,
+ ApkKeystoreInfo keystoreInfo,
+ BuildMode buildMode,
) {
File keystore;
String keystorePassword;
@@ -405,7 +409,12 @@
String keyPassword;
if (keystoreInfo == null) {
- printStatus('Warning: signing the APK using the debug keystore.');
+ if (buildMode == BuildMode.release) {
+ printStatus('Warning! Signing the APK using the debug keystore.');
+ printStatus('You will need a real keystore to distribute your application.');
+ } else {
+ printTrace('Signing the APK using the debug keystore.');
+ }
keystore = components.debugKeystore;
keystorePassword = _kDebugKeystorePassword;
keyAlias = _kDebugKeystoreKeyAlias;
@@ -415,7 +424,7 @@
keystorePassword = keystoreInfo.password ?? '';
keyAlias = keystoreInfo.keyAlias ?? '';
if (keystorePassword.isEmpty || keyAlias.isEmpty) {
- printError('Must provide a keystore password and a key alias.');
+ printError('You must provide a keystore password and a key alias.');
return 1;
}
keyPassword = keystoreInfo.keyPassword ?? '';
@@ -586,7 +595,7 @@
if (result == 0) {
File apkFile = new File(outputFile);
- printStatus('Built $outputFile (${getSizeAsMB(apkFile.lengthSync())}).');
+ printTrace('Built $outputFile (${getSizeAsMB(apkFile.lengthSync())}).');
_writeBuildMetaEntry(
path.dirname(outputFile),
diff --git a/packages/flutter_tools/lib/src/hot.dart b/packages/flutter_tools/lib/src/hot.dart
index 1d27d12..4e4f4a0 100644
--- a/packages/flutter_tools/lib/src/hot.dart
+++ b/packages/flutter_tools/lib/src/hot.dart
@@ -6,6 +6,7 @@
import 'dart:convert';
import 'dart:io';
+import 'package:meta/meta.dart';
import 'package:path/path.dart' as path;
import 'package:stack_trace/stack_trace.dart';
@@ -135,6 +136,7 @@
String _mainPath;
String _projectRootPath;
Set<String> _startupDependencies;
+ int _observatoryPort;
final AssetBundle bundle = new AssetBundle();
final bool benchmarkMode;
final Map<String, int> benchmarkData = new Map<String, int>();
@@ -217,7 +219,7 @@
await startEchoingDeviceLog();
- printStatus('Launching loader on ${device.name}...');
+ printTrace('Launching loader on ${device.name}...');
// Start the loader.
Future<LaunchResult> futureResult = device.startApp(
@@ -246,13 +248,14 @@
return 2;
}
- await connectToServiceProtocol(result.observatoryPort);
+ _observatoryPort = result.observatoryPort;
+ await connectToServiceProtocol(_observatoryPort);
try {
Uri baseUri = await _initDevFS();
if (connectionInfoCompleter != null) {
connectionInfoCompleter.complete(
- new DebugConnectionInfo(result.observatoryPort, baseUri: baseUri.toString())
+ new DebugConnectionInfo(_observatoryPort, baseUri: baseUri.toString())
);
}
} catch (error) {
@@ -273,13 +276,13 @@
}
await vmService.vm.refreshViews();
- printStatus('Connected to ${vmService.vm.mainView}.');
+ printTrace('Connected to ${vmService.vm.mainView}.');
printStatus('Running ${getDisplayPath(_mainPath)} on ${device.name}...');
_loaderShowMessage('Launching...');
await _launchFromDevFS(_package, _mainPath);
- printStatus('Application running.');
+ printTrace('Application running.');
setupTerminal();
@@ -361,10 +364,7 @@
devFSStatus.stop(showElapsedTime: true);
// Clear the minimal set after the first sync.
_startupDependencies = null;
- if (progressReporter != null)
- printStatus('Synced ${getSizeAsMB(_devFS.bytes)}.');
- else
- printTrace('Synced ${getSizeAsMB(_devFS.bytes)}.');
+ printTrace('Synced ${getSizeAsMB(_devFS.bytes)}.');
return true;
}
@@ -537,10 +537,16 @@
}
@override
- void printHelp() {
- printStatus('Type "h" or F1 for this help message; type "q", F10, or ctrl-c to quit.', emphasis: true);
- printStatus('Type "r" or F5 to perform a hot reload of the app, and "R" to restart the app.', emphasis: true);
- printStatus('Type "w" to print the widget hierarchy of the app, and "t" for the render tree.', emphasis: true);
+ void printHelp({ @required bool details }) {
+ printStatus('To hot reload your app on the fly, press "r" or F5. To restart the app entirely, press "R".', emphasis: true);
+ printStatus('The Observatory debugger and profiler is available at: http://127.0.0.1:$_observatoryPort/');
+ if (details) {
+ printStatus('To dump the widget hierarchy of the app (debugDumpApp), press "w".');
+ printStatus('To dump the rendering tree of the app (debugDumpRenderTree), press "r".');
+ printStatus('To repeat this help message, press "h" or F1. To quit, press "q", F10, or Ctrl-C.');
+ } else {
+ printStatus('For a more detailed help message, press "h" or F1. To quit, press "q", F10, or Ctrl-C.');
+ }
}
@override
diff --git a/packages/flutter_tools/lib/src/resident_runner.dart b/packages/flutter_tools/lib/src/resident_runner.dart
index a9524b2..f8d9fb6 100644
--- a/packages/flutter_tools/lib/src/resident_runner.dart
+++ b/packages/flutter_tools/lib/src/resident_runner.dart
@@ -5,6 +5,7 @@
import 'dart:async';
import 'dart:io';
+import 'package:meta/meta.dart';
import 'package:path/path.dart' as path;
import 'base/logger.dart';
@@ -126,7 +127,7 @@
if (lower == 'h' || lower == '?' || character == AnsiTerminal.KEY_F1) {
// F1, help
- printHelp();
+ printHelp(details: true);
return true;
} else if (lower == 'w') {
await _debugDumpApp();
@@ -165,7 +166,7 @@
void setupTerminal() {
if (usesTerminalUI) {
if (!logger.quiet)
- printHelp();
+ printHelp(details: false);
terminal.singleCharMode = true;
terminal.onCharInput.listen((String code) {
@@ -198,7 +199,7 @@
/// Called right before we exit.
Future<Null> cleanupAtFinish();
/// Called to print help to the terminal.
- void printHelp();
+ void printHelp({ @required bool details });
/// Called when the runner should handle a terminal command.
Future<Null> handleTerminalCommand(String code);
}
diff --git a/packages/flutter_tools/lib/src/run.dart b/packages/flutter_tools/lib/src/run.dart
index 2fd0ea5..216253f 100644
--- a/packages/flutter_tools/lib/src/run.dart
+++ b/packages/flutter_tools/lib/src/run.dart
@@ -5,6 +5,7 @@
import 'dart:async';
import 'dart:io';
+import 'package:meta/meta.dart';
import 'package:stack_trace/stack_trace.dart';
import 'application_package.dart';
@@ -197,13 +198,13 @@
}
}
- printStatus('Application running.');
+ printTrace('Application running.');
if (debuggingOptions.buildMode == BuildMode.release)
return 0;
if (vmService != null) {
await vmService.vm.refreshViews();
- printStatus('Connected to ${vmService.vm.mainView}\.');
+ printTrace('Connected to ${vmService.vm.mainView}\.');
}
if (vmService != null && traceStartup) {
@@ -261,11 +262,18 @@
}
@override
- void printHelp() {
- final bool showRestartText = !prebuiltMode && device.supportsRestart;
- String restartText = showRestartText ? ', "r" or F5 to restart the app,' : '';
- printStatus('Type "h" or F1 for help$restartText and "q", F10, or ctrl-c to quit.');
- printStatus('Type "w" to print the widget hierarchy of the app, and "t" for the render tree.');
+ void printHelp({ @required bool details }) {
+ if (!prebuiltMode && device.supportsRestart)
+ printStatus('To restart the app, press "r" or F5.');
+ if (_result.hasObservatory)
+ printStatus('The Observatory debugger and profiler is available at: http://127.0.0.1:${_result.observatoryPort}/');
+ if (details) {
+ printStatus('To dump the widget hierarchy of the app (debugDumpApp), press "w".');
+ printStatus('To dump the rendering tree of the app (debugDumpRenderTree), press "r".');
+ printStatus('To repeat this help message, press "h" or F1. To quit, press "q", F10, or Ctrl-C.');
+ } else {
+ printStatus('For a more detailed help message, press "h" or F1. To quit, press "q", F10, or Ctrl-C.');
+ }
}
}