tvOS, watchOS and old simulators are blacklisted in the tools
diff --git a/packages/flutter_tools/lib/src/android/device_android.dart b/packages/flutter_tools/lib/src/android/device_android.dart index 0270def..404c0d8 100644 --- a/packages/flutter_tools/lib/src/android/device_android.dart +++ b/packages/flutter_tools/lib/src/android/device_android.dart
@@ -392,6 +392,8 @@ bool isConnected() => _connected ?? androidSdk != null; + bool isSupported() => true; + void setConnected(bool value) { _connected = value; }
diff --git a/packages/flutter_tools/lib/src/commands/devices.dart b/packages/flutter_tools/lib/src/commands/devices.dart index 6531c63..817c9eb 100644 --- a/packages/flutter_tools/lib/src/commands/devices.dart +++ b/packages/flutter_tools/lib/src/commands/devices.dart
@@ -28,10 +28,12 @@ printStatus('No connected devices.'); } else { printStatus('${devices.length} connected ${pluralize('device', devices.length)}:'); - printStatus(''); for (Device device in devices) { - printStatus('${device.name} (${device.id})'); + printStatus('\t${_supportIndicator(device)}: ${device.name} (${device.id})'); + if (!device.isSupported()) { + printStatus("\t\t${device.supportMessage()}"); + } } } @@ -39,4 +41,6 @@ } } +String _supportIndicator(Device device) => device.isSupported() ? "[✔] Supported" : "[✘] Unsupported"; + String pluralize(String word, int count) => count == 1 ? word : word + 's';
diff --git a/packages/flutter_tools/lib/src/commands/run.dart b/packages/flutter_tools/lib/src/commands/run.dart index c4fcb7b..7a92edb 100644 --- a/packages/flutter_tools/lib/src/commands/run.dart +++ b/packages/flutter_tools/lib/src/commands/run.dart
@@ -179,6 +179,11 @@ if (package == null || !device.isConnected()) continue; + if (!device.isSupported()) { + printStatus("Skipping unsupported device: ${device.name}"); + continue; + } + printTrace('Running build command for $device.'); Map<String, dynamic> platformArgs = <String, dynamic>{}; @@ -215,11 +220,7 @@ } if (!startedSomething) { - if (!devices.all.any((device) => device.isConnected())) { - printError('Unable to run application - no connected devices.'); - } else { - printError('Unable to run application.'); - } + printError('Unable to run application. Please ensure that a supported device/simulator is connected.'); } return startedSomething ? 0 : 2;
diff --git a/packages/flutter_tools/lib/src/device.dart b/packages/flutter_tools/lib/src/device.dart index 28c9333..04562ad 100644 --- a/packages/flutter_tools/lib/src/device.dart +++ b/packages/flutter_tools/lib/src/device.dart
@@ -106,6 +106,13 @@ /// Check if the device is currently connected bool isConnected(); + /// Check if the device is supported by Flutter + bool isSupported(); + + // String meant to be displayed to the user indicating if the device is + // supported by Flutter, and, if not, why. + String supportMessage() => isSupported() ? "Supported" : "Unsupported"; + /// Check if the current version of the given app is already installed bool isAppInstalled(ApplicationPackage app);
diff --git a/packages/flutter_tools/lib/src/ios/device_ios.dart b/packages/flutter_tools/lib/src/ios/device_ios.dart index 0225701..10bb965 100644 --- a/packages/flutter_tools/lib/src/ios/device_ios.dart +++ b/packages/flutter_tools/lib/src/ios/device_ios.dart
@@ -150,6 +150,9 @@ bool isConnected() => _getAttachedDeviceIDs().contains(id); @override + bool isSupported() => true; + + @override bool isAppInstalled(ApplicationPackage app) { try { String apps = runCheckedSync([installerPath, '--list-apps']); @@ -292,6 +295,61 @@ } @override + bool isSupported() { + if (!Platform.isMacOS) { + _supportMessage = "Not supported on a non Mac host"; + return false; + } + + // Step 1: Check if the device is part of a blacklisted category. + // We do not support WatchOS or tvOS devices. + + RegExp blacklist = new RegExp(r'Apple (TV|Watch)', caseSensitive: false); + + if (blacklist.hasMatch(name)) { + _supportMessage = "Flutter does not support either the Apple TV or Watch. Choose an iPhone 5s or above."; + return false; + } + + // Step 2: Check if the device must be rejected because of its version. + // There is an artitifical check on older simulators where arm64 + // targetted applications cannot be run (even though the + // Flutter runner on the simulator is completely different). + + RegExp versionExp = new RegExp(r'iPhone ([0-9])+'); + Match match = versionExp.firstMatch(name); + + if (match == null) { + // Not an iPhone. All available non-iPhone simulators are compatible. + return true; + } + + if (int.parse(match.group(1)) > 5) { + // iPhones 6 and above are always fine. + return true; + } + + // The 's' subtype of 5 is compatible. + if (name.contains('iPhone 5s')) { + return true; + } + + _supportMessage = "The simulator version is too old. Choose an iPhone 5s or above."; + return false; + } + + String _supportMessage; + + @override + String supportMessage() { + if (isSupported()) { + return "Supported"; + } + + return _supportMessage != null ? _supportMessage : "Unknown"; + } + + @override bool isAppInstalled(ApplicationPackage app) { try { String simulatorHomeDirectory = _getSimulatorAppHomeDirectory(app);