Fix install for iOS simulator, and add ability to uninstall (#4223)
diff --git a/packages/flutter_tools/lib/src/android/android_device.dart b/packages/flutter_tools/lib/src/android/android_device.dart
index 1ae3359..b7051e3 100644
--- a/packages/flutter_tools/lib/src/android/android_device.dart
+++ b/packages/flutter_tools/lib/src/android/android_device.dart
@@ -232,6 +232,22 @@
return true;
}
+ @override
+ bool uninstallApp(ApplicationPackage app) {
+ if (!_checkForSupportedAdbVersion() || !_checkForSupportedAndroidVersion())
+ return false;
+
+ String uninstallOut = runCheckedSync(adbCommandForDevice(<String>['uninstall', app.id]));
+ RegExp failureExp = new RegExp(r'^Failure.*$', multiLine: true);
+ String failure = failureExp.stringMatch(uninstallOut);
+ if (failure != null) {
+ printError('Package uninstall error: $failure');
+ return false;
+ }
+
+ return true;
+ }
+
Future<Null> _forwardPort(String service, int devicePort, int port) async {
try {
// Set up port forwarding for observatory.
diff --git a/packages/flutter_tools/lib/src/commands/drive.dart b/packages/flutter_tools/lib/src/commands/drive.dart
index b9b2747..e5c754e 100644
--- a/packages/flutter_tools/lib/src/commands/drive.dart
+++ b/packages/flutter_tools/lib/src/commands/drive.dart
@@ -274,6 +274,8 @@
printTrace('Installing application package.');
ApplicationPackage package = command.applicationPackages
.getPackageForPlatform(command.device.platform);
+ if (command.device.isAppInstalled(package))
+ command.device.uninstallApp(package);
command.device.installApp(package);
Map<String, dynamic> platformArgs = <String, dynamic>{};
diff --git a/packages/flutter_tools/lib/src/commands/install.dart b/packages/flutter_tools/lib/src/commands/install.dart
index c3ae09c..ab2ebb1 100644
--- a/packages/flutter_tools/lib/src/commands/install.dart
+++ b/packages/flutter_tools/lib/src/commands/install.dart
@@ -34,8 +34,11 @@
if (package == null)
return false;
- if (device.isAppInstalled(package))
- return true;
+ if (device.isAppInstalled(package)) {
+ printStatus('Uninstalling old version...');
+ if (!device.uninstallApp(package))
+ printError('Warning: uninstalling old version failed');
+ }
return device.installApp(package);
}
diff --git a/packages/flutter_tools/lib/src/device.dart b/packages/flutter_tools/lib/src/device.dart
index f67c0d3..d0451f0 100644
--- a/packages/flutter_tools/lib/src/device.dart
+++ b/packages/flutter_tools/lib/src/device.dart
@@ -149,9 +149,15 @@
/// Whether it is an emulated device running on localhost.
bool get isLocalEmulator;
+ /// Check if a version of the given app is already installed
+ bool isAppInstalled(ApplicationPackage app);
+
/// Install an app package on the current device
bool installApp(ApplicationPackage app);
+ /// Uninstall an app package from the current device
+ bool uninstallApp(ApplicationPackage app);
+
/// Check if the device is supported by Flutter
bool isSupported();
@@ -159,9 +165,6 @@
// 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);
-
TargetPlatform get platform;
/// Get the log reader for this device.
diff --git a/packages/flutter_tools/lib/src/ios/devices.dart b/packages/flutter_tools/lib/src/ios/devices.dart
index 321ab3a..c86cf80 100644
--- a/packages/flutter_tools/lib/src/ios/devices.dart
+++ b/packages/flutter_tools/lib/src/ios/devices.dart
@@ -124,21 +124,6 @@
}
@override
- bool installApp(ApplicationPackage app) {
- try {
- IOSApp iosApp = app;
- runCheckedSync(<String>[installerPath, '-i', iosApp.deviceBundlePath]);
- return true;
- } catch (e) {
- return false;
- }
- return false;
- }
-
- @override
- bool isSupported() => true;
-
- @override
bool isAppInstalled(ApplicationPackage app) {
try {
String apps = runCheckedSync(<String>[installerPath, '--list-apps']);
@@ -152,6 +137,36 @@
}
@override
+ bool installApp(ApplicationPackage app) {
+ IOSApp iosApp = app;
+ Directory bundle = new Directory(iosApp.deviceBundlePath);
+ if (!bundle.existsSync()) {
+ printError("Could not find application bundle at ${bundle.path}; have you run 'flutter build ios'?");
+ return false;
+ }
+
+ try {
+ runCheckedSync(<String>[installerPath, '-i', iosApp.deviceBundlePath]);
+ return true;
+ } catch (e) {
+ return false;
+ }
+ }
+
+ @override
+ bool uninstallApp(ApplicationPackage app) {
+ try {
+ runCheckedSync(<String>[installerPath, '-U', app.id]);
+ return true;
+ } catch (e) {
+ return false;
+ }
+ }
+
+ @override
+ bool isSupported() => true;
+
+ @override
Future<LaunchResult> startApp(
ApplicationPackage app,
BuildMode mode, {
@@ -174,8 +189,7 @@
// Step 2: Check that the application exists at the specified path.
IOSApp iosApp = app;
Directory bundle = new Directory(iosApp.deviceBundlePath);
- bool bundleExists = bundle.existsSync();
- if (!bundleExists) {
+ if (!bundle.existsSync()) {
printError('Could not find the built application bundle at ${bundle.path}.');
return new LaunchResult.failed();
}
diff --git a/packages/flutter_tools/lib/src/ios/simulators.dart b/packages/flutter_tools/lib/src/ios/simulators.dart
index f566a14..58ae15b 100644
--- a/packages/flutter_tools/lib/src/ios/simulators.dart
+++ b/packages/flutter_tools/lib/src/ios/simulators.dart
@@ -274,10 +274,24 @@
bool _isAnyConnected() => getConnectedDevices().isNotEmpty;
+ bool isInstalled(String appId) {
+ return exitsHappy(<String>[
+ _xcrunPath,
+ 'simctl',
+ 'get_app_container',
+ 'booted',
+ appId,
+ ]);
+ }
+
void install(String deviceId, String appPath) {
runCheckedSync(<String>[_xcrunPath, 'simctl', 'install', deviceId, appPath]);
}
+ void uninstall(String deviceId, String appId) {
+ runCheckedSync(<String>[_xcrunPath, 'simctl', 'uninstall', deviceId, appId]);
+ }
+
void launch(String deviceId, String appIdentifier, [List<String> launchArgs]) {
List<String> args = <String>[_xcrunPath, 'simctl', 'launch', deviceId, appIdentifier];
if (launchArgs != null)
@@ -362,6 +376,11 @@
}
@override
+ bool isAppInstalled(ApplicationPackage app) {
+ return SimControl.instance.isInstalled(app.id);
+ }
+
+ @override
bool installApp(ApplicationPackage app) {
try {
IOSApp iosApp = app;
@@ -373,6 +392,16 @@
}
@override
+ bool uninstallApp(ApplicationPackage app) {
+ try {
+ SimControl.instance.uninstall(id, app.id);
+ return true;
+ } catch (e) {
+ return false;
+ }
+ }
+
+ @override
bool isSupported() {
if (!Platform.isMacOS) {
_supportMessage = "Not supported on a non Mac host";
@@ -424,17 +453,6 @@
}
@override
- bool isAppInstalled(ApplicationPackage app) {
- try {
- // TODO(tvolkert): This logic is wrong; simulatorHomeDirectory always exists
- String simulatorHomeDirectory = _getSimulatorAppHomeDirectory(app);
- return FileSystemEntity.isDirectorySync(simulatorHomeDirectory);
- } catch (e) {
- return false;
- }
- }
-
- @override
Future<LaunchResult> startApp(
ApplicationPackage app,
BuildMode mode, {
@@ -505,13 +523,7 @@
}
bool _applicationIsInstalledAndRunning(ApplicationPackage app) {
- bool isInstalled = exitsHappy(<String>[
- 'xcrun',
- 'simctl',
- 'get_app_container',
- 'booted',
- app.id,
- ]);
+ bool isInstalled = isAppInstalled(app);
bool isRunning = exitsHappy(<String>[
'/usr/bin/killall',