diff --git a/packages/flutter_tools/lib/src/application_package.dart b/packages/flutter_tools/lib/src/application_package.dart index 9857a24420c..35fae609589 100644 --- a/packages/flutter_tools/lib/src/application_package.dart +++ b/packages/flutter_tools/lib/src/application_package.dart @@ -3,8 +3,10 @@ // found in the LICENSE file. import 'dart:async'; +import 'dart:io'; import 'package:path/path.dart' as path; +import 'package:xml/xml.dart' as xml; import 'artifacts.dart'; import 'build_configuration.dart'; @@ -32,6 +34,8 @@ class AndroidApk extends ApplicationPackage { static const String _defaultName = 'SkyShell.apk'; static const String _defaultId = 'org.domokit.sky.shell'; static const String _defaultLaunchActivity = '$_defaultId/$_defaultId.SkyActivity'; + static const String _defaultManifestPath = 'apk/AndroidManifest.xml'; + static const String _defaultOutputPath = 'build/app.apk'; /// The path to the activity that should be launched. /// Defaults to 'org.domokit.sky.shell/org.domokit.sky.shell.SkyActivity' @@ -44,6 +48,36 @@ class AndroidApk extends ApplicationPackage { }) : super(localPath: localPath, id: id) { assert(launchActivity != null); } + + /// Creates a new AndroidApk based on the information in the Android manifest. + static AndroidApk getCustomApk({ + String localPath: _defaultOutputPath, + String manifest: _defaultManifestPath + }) { + if (!FileSystemEntity.isFileSync(manifest)) + return null; + String manifestString = new File(manifest).readAsStringSync(); + xml.XmlDocument document = xml.parse(manifestString); + + Iterable manifests = document.findElements('manifest'); + if (manifests.isEmpty) + return null; + String id = manifests.first.getAttribute('package'); + + String launchActivity; + for (xml.XmlElement category in document.findAllElements('category')) { + if (category.getAttribute('android:name') == 'android.intent.category.LAUNCHER') { + xml.XmlElement activity = category.parent.parent as xml.XmlElement; + String activityName = activity.getAttribute('android:name'); + launchActivity = "$id/$activityName"; + break; + } + } + if (id == null || launchActivity == null) + return null; + + return new AndroidApk(localPath: localPath, id: id, launchActivity: launchActivity); + } } class IOSApp extends ApplicationPackage { @@ -86,7 +120,13 @@ class ApplicationPackageStore { switch (config.targetPlatform) { case TargetPlatform.android: assert(android == null); - if (config.type != BuildType.prebuilt) { + android = AndroidApk.getCustomApk(); + // Fall back to the prebuilt or engine-provided apk if we can't build + // a custom one. + // TODO(mpcomplete): we should remove both these fallbacks. + if (android != null) { + break; + } else if (config.type != BuildType.prebuilt) { String localPath = path.join(config.buildDir, 'apks', AndroidApk._defaultName); android = new AndroidApk(localPath: localPath); } else { diff --git a/packages/flutter_tools/lib/src/commands/apk.dart b/packages/flutter_tools/lib/src/commands/apk.dart index 14bbaef7cbf..14070c95fbb 100644 --- a/packages/flutter_tools/lib/src/commands/apk.dart +++ b/packages/flutter_tools/lib/src/commands/apk.dart @@ -8,7 +8,6 @@ import 'dart:io'; import 'package:path/path.dart' as path; import 'package:yaml/yaml.dart'; -import 'package:xml/xml.dart' as xml; import '../android/device_android.dart'; import '../application_package.dart'; @@ -406,33 +405,6 @@ int _signApk( return 0; } -// Creates a new ApplicationPackage from the Android manifest. -AndroidApk _getApplicationPackage(String apkPath, String manifest) { - if (!FileSystemEntity.isFileSync(manifest)) - return null; - String manifestString = new File(manifest).readAsStringSync(); - xml.XmlDocument document = xml.parse(manifestString); - - Iterable manifests = document.findElements('manifest'); - if (manifests.isEmpty) - return null; - String id = manifests.toList()[0].getAttribute('package'); - - String launchActivity; - for (xml.XmlElement category in document.findAllElements('category')) { - if (category.getAttribute('android:name') == 'android.intent.category.LAUNCHER') { - xml.XmlElement activity = category.parent.parent as xml.XmlElement; - String activityName = activity.getAttribute('android:name'); - launchActivity = "$id/$activityName"; - break; - } - } - if (id == null || launchActivity == null) - return null; - - return new AndroidApk(localPath: apkPath, id: id, launchActivity: launchActivity); -} - // Returns true if the apk is out of date and needs to be rebuilt. bool _needsRebuild(String apkPath, String manifest) { FileStat apkStat = FileStat.statSync(apkPath); @@ -504,7 +476,8 @@ Future buildAndroid({ } } -Future buildAll( +// TODO(mpcomplete): move this to Device? +Future buildAll( DeviceStore devices, ApplicationPackageStore applicationPackages, Toolchain toolchain, @@ -531,13 +504,6 @@ Future buildAll( force: false, target: target ); - // Replace our pre-built AndroidApk with this custom-built one. - applicationPackages = new ApplicationPackageStore( - android: _getApplicationPackage(_kDefaultOutputPath, _kDefaultAndroidManifestPath), - iOS: applicationPackages.iOS, - iOSSimulator: applicationPackages.iOSSimulator - ); } } - return applicationPackages; } diff --git a/packages/flutter_tools/lib/src/commands/start.dart b/packages/flutter_tools/lib/src/commands/start.dart index bfa0a9a6340..ba653b080b9 100644 --- a/packages/flutter_tools/lib/src/commands/start.dart +++ b/packages/flutter_tools/lib/src/commands/start.dart @@ -142,7 +142,7 @@ Future startApp( if (install) { printTrace('Running build command.'); - applicationPackages = await buildAll( + await buildAll( devices, applicationPackages, toolchain, configs, enginePath: enginePath, target: target);