Commit 51d4ab33 authored by Todd Volkert's avatar Todd Volkert

Fix install for iOS simulator, and add ability to uninstall (#4223)

parent 1a05b696
......@@ -232,6 +232,22 @@ class AndroidDevice extends Device {
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.
......
......@@ -274,6 +274,8 @@ Future<int> startApp(DriveCommand command) async {
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>{};
......
......@@ -34,8 +34,11 @@ bool installApp(Device device, ApplicationPackage package) {
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);
}
......@@ -149,9 +149,15 @@ abstract class Device {
/// 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 @@ abstract class Device {
// 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.
......
......@@ -124,11 +124,12 @@ class IOSDevice extends Device {
}
@override
bool installApp(ApplicationPackage app) {
bool isAppInstalled(ApplicationPackage app) {
try {
IOSApp iosApp = app;
runCheckedSync(<String>[installerPath, '-i', iosApp.deviceBundlePath]);
return true;
String apps = runCheckedSync(<String>[installerPath, '--list-apps']);
if (new RegExp(app.id, multiLine: true).hasMatch(apps)) {
return true;
}
} catch (e) {
return false;
}
......@@ -136,21 +137,35 @@ class IOSDevice extends Device {
}
@override
bool isSupported() => true;
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 isAppInstalled(ApplicationPackage app) {
bool uninstallApp(ApplicationPackage app) {
try {
String apps = runCheckedSync(<String>[installerPath, '--list-apps']);
if (new RegExp(app.id, multiLine: true).hasMatch(apps)) {
return true;
}
runCheckedSync(<String>[installerPath, '-U', app.id]);
return true;
} catch (e) {
return false;
}
return false;
}
@override
bool isSupported() => true;
@override
Future<LaunchResult> startApp(
ApplicationPackage app,
......@@ -174,8 +189,7 @@ class IOSDevice extends Device {
// 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();
}
......
......@@ -274,10 +274,24 @@ class SimControl {
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)
......@@ -361,6 +375,11 @@ class IOSSimulator extends Device {
return path.join(simulatorPath, 'data');
}
@override
bool isAppInstalled(ApplicationPackage app) {
return SimControl.instance.isInstalled(app.id);
}
@override
bool installApp(ApplicationPackage app) {
try {
......@@ -372,6 +391,16 @@ class IOSSimulator extends Device {
}
}
@override
bool uninstallApp(ApplicationPackage app) {
try {
SimControl.instance.uninstall(id, app.id);
return true;
} catch (e) {
return false;
}
}
@override
bool isSupported() {
if (!Platform.isMacOS) {
......@@ -423,17 +452,6 @@ class IOSSimulator extends Device {
return _supportMessage != null ? _supportMessage : "Unknown";
}
@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,
......@@ -505,13 +523,7 @@ class IOSSimulator extends Device {
}
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',
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment