Commit cc8c78ad authored by Todd Volkert's avatar Todd Volkert

iOS tools cleanup (#4161)

* iOS tools cleanup

1) Fix `flutter install` on both device and simulator to refer to the actual
   bundle and not just the .generated folder
2) Fix `flutter run` on device to actually run vs just installing

Still TODO:
1) Discovered that isAppInstalled on iOS simulator always reports true,
   meaning it'll never actually try to install the app.

Fixes #3947
Fixes #1823
parent 2d726fc0
......@@ -187,7 +187,8 @@ class AndroidDevice extends Device {
}
String _getSourceSha1(ApplicationPackage app) {
File shaFile = new File('${app.localPath}.sha1');
AndroidApk apk = app;
File shaFile = new File('${apk.apkPath}.sha1');
return shaFile.existsSync() ? shaFile.readAsStringSync() : '';
}
......@@ -207,15 +208,16 @@ class AndroidDevice extends Device {
@override
bool installApp(ApplicationPackage app) {
if (!FileSystemEntity.isFileSync(app.localPath)) {
printError('"${app.localPath}" does not exist.');
AndroidApk apk = app;
if (!FileSystemEntity.isFileSync(apk.apkPath)) {
printError('"${apk.apkPath}" does not exist.');
return false;
}
if (!_checkForSupportedAdbVersion() || !_checkForSupportedAndroidVersion())
return false;
String installOut = runCheckedSync(adbCommandForDevice(<String>['install', '-r', app.localPath]));
String installOut = runCheckedSync(adbCommandForDevice(<String>['install', '-r', apk.apkPath]));
RegExp failureExp = new RegExp(r'^Failure.*$', multiLine: true);
String failure = failureExp.stringMatch(installOut);
if (failure != null) {
......
......@@ -11,23 +11,19 @@ import 'build_info.dart';
import 'ios/plist_utils.dart';
abstract class ApplicationPackage {
/// Path to the actual apk or bundle.
final String localPath;
/// Path to the package's root folder.
final String rootPath;
/// Package ID from the Android Manifest or equivalent.
final String id;
/// File name of the apk or bundle.
final String name;
ApplicationPackage({
String localPath,
this.id
}) : localPath = localPath, name = path.basename(localPath) {
assert(localPath != null);
ApplicationPackage({this.rootPath, this.id}) {
assert(rootPath != null);
assert(id != null);
}
String get name;
String get displayName => name;
@override
......@@ -35,14 +31,19 @@ abstract class ApplicationPackage {
}
class AndroidApk extends ApplicationPackage {
/// Path to the actual apk file.
final String apkPath;
/// The path to the activity that should be launched.
final String launchActivity;
AndroidApk({
String localPath,
String buildDir,
String id,
this.apkPath,
this.launchActivity
}) : super(localPath: localPath, id: id) {
}) : super(rootPath: buildDir, id: id) {
assert(apkPath != null);
assert(launchActivity != null);
}
......@@ -71,16 +72,25 @@ class AndroidApk extends ApplicationPackage {
if (id == null || launchActivity == null)
return null;
String localPath = path.join('build', 'app.apk');
return new AndroidApk(localPath: localPath, id: id, launchActivity: launchActivity);
return new AndroidApk(
buildDir: 'build',
id: id,
apkPath: path.join('build', 'app.apk'),
launchActivity: launchActivity
);
}
@override
String get name => path.basename(apkPath);
}
class IOSApp extends ApplicationPackage {
static final String kBundleName = 'Runner.app';
IOSApp({
String iosProjectDir,
String iosProjectBundleId
}) : super(localPath: iosProjectDir, id: iosProjectBundleId);
String projectDir,
String projectBundleId
}) : super(rootPath: projectDir, id: projectBundleId);
factory IOSApp.fromCurrentDirectory() {
if (getCurrentHostPlatform() != HostPlatform.darwin_x64)
......@@ -91,12 +101,25 @@ class IOSApp extends ApplicationPackage {
if (value == null)
return null;
String projectDir = path.join('ios', '.generated');
return new IOSApp(iosProjectDir: projectDir, iosProjectBundleId: value);
return new IOSApp(
projectDir: path.join('ios', '.generated'),
projectBundleId: value
);
}
@override
String get name => kBundleName;
@override
String get displayName => id;
String get simulatorBundlePath => _buildAppPath('iphonesimulator');
String get deviceBundlePath => _buildAppPath('iphoneos');
String _buildAppPath(String type) {
return path.join(rootPath, 'build', 'Release-$type', kBundleName);
}
}
ApplicationPackage getApplicationPackageForPlatform(TargetPlatform platform) {
......
......@@ -6,8 +6,6 @@ import 'dart:async';
import 'dart:convert';
import 'dart:io';
import 'package:path/path.dart' as path;
import '../application_package.dart';
import '../base/os.dart';
import '../base/process.dart';
......@@ -127,7 +125,8 @@ class IOSDevice extends Device {
@override
bool installApp(ApplicationPackage app) {
try {
runCheckedSync(<String>[installerPath, '-i', app.localPath]);
IOSApp iosApp = app;
runCheckedSync(<String>[installerPath, '-i', iosApp.deviceBundlePath]);
return true;
} catch (e) {
return false;
......@@ -172,7 +171,8 @@ class IOSDevice extends Device {
}
// Step 2: Check that the application exists at the specified path.
Directory bundle = new Directory(path.join(app.localPath, 'build', 'Release-iphoneos', 'Runner.app'));
IOSApp iosApp = app;
Directory bundle = new Directory(iosApp.deviceBundlePath);
bool bundleExists = bundle.existsSync();
if (!bundleExists) {
printError('Could not find the built application bundle at ${bundle.path}.');
......@@ -187,6 +187,7 @@ class IOSDevice extends Device {
id,
'--bundle',
bundle.path,
'--justlaunch',
]);
if (installationResult != 0) {
......
......@@ -120,7 +120,7 @@ Future<bool> buildIOSXcodeProject(ApplicationPackage app, BuildMode mode,
// Before the build, all service definitions must be updated and the dylibs
// copied over to a location that is suitable for Xcodebuild to find them.
await _addServicesToBundle(new Directory(app.localPath));
await _addServicesToBundle(new Directory(app.rootPath));
List<String> commands = <String>[
'/usr/bin/env',
......@@ -151,7 +151,7 @@ Future<bool> buildIOSXcodeProject(ApplicationPackage app, BuildMode mode,
printTrace(commands.join(' '));
ProcessResult result = Process.runSync(
commands.first, commands.sublist(1), workingDirectory: app.localPath
commands.first, commands.sublist(1), workingDirectory: app.rootPath
);
if (result.exitCode != 0) {
......@@ -199,7 +199,7 @@ bool _validateEngineRevision(ApplicationPackage app) {
}
String _getIOSEngineRevision(ApplicationPackage app) {
File revisionFile = new File(path.join(app.localPath, 'REVISION'));
File revisionFile = new File(path.join(app.rootPath, 'REVISION'));
if (revisionFile.existsSync()) {
// The format is 'REVISION-mode'. We only need the revision.
String revisionStamp = revisionFile.readAsStringSync().trim();
......
......@@ -363,7 +363,8 @@ class IOSSimulator extends Device {
@override
bool installApp(ApplicationPackage app) {
try {
SimControl.instance.install(id, app.localPath);
IOSApp iosApp = app;
SimControl.instance.install(id, iosApp.simulatorBundlePath);
return true;
} catch (e) {
return false;
......@@ -424,6 +425,7 @@ class IOSSimulator extends Device {
@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) {
......@@ -540,7 +542,8 @@ class IOSSimulator extends Device {
}
// Step 2: Assert that the Xcode project was successfully built.
Directory bundle = new Directory(path.join(app.localPath, 'build', 'Release-iphonesimulator', 'Runner.app'));
IOSApp iosApp = app;
Directory bundle = new Directory(iosApp.simulatorBundlePath);
bool bundleExists = await bundle.exists();
if (!bundleExists) {
printError('Could not find the built application bundle at ${bundle.path}.');
......
......@@ -16,13 +16,14 @@ import 'package:mockito/mockito.dart';
class MockApplicationPackageStore extends ApplicationPackageStore {
MockApplicationPackageStore() : super(
android: new AndroidApk(
localPath: '/mock/path/to/android/SkyShell.apk',
buildDir: '/mock/path/to/android',
id: 'io.flutter.android.mock',
apkPath: '/mock/path/to/android/SkyShell.apk',
launchActivity: 'io.flutter.android.mock.MockActivity'
),
iOS: new IOSApp(
iosProjectDir: '/mock/path/to/iOS/SkyShell.app',
iosProjectBundleId: 'io.flutter.ios.mock'
projectDir: '/mock/path/to/iOS/SkyShell.app',
projectBundleId: 'io.flutter.ios.mock'
)
);
}
......
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