diff --git a/dev/manual_tests/android/AndroidManifest.xml b/dev/manual_tests/android/AndroidManifest.xml
new file mode 100644
index 0000000000..98a4eaf553
--- /dev/null
+++ b/dev/manual_tests/android/AndroidManifest.xml
@@ -0,0 +1,19 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/examples/hello_world/android/AndroidManifest.xml b/examples/hello_world/android/AndroidManifest.xml
new file mode 100644
index 0000000000..6d96b4e727
--- /dev/null
+++ b/examples/hello_world/android/AndroidManifest.xml
@@ -0,0 +1,19 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/examples/layers/android/AndroidManifest.xml b/examples/layers/android/AndroidManifest.xml
new file mode 100644
index 0000000000..e81d6863a6
--- /dev/null
+++ b/examples/layers/android/AndroidManifest.xml
@@ -0,0 +1,19 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/packages/flutter_tools/lib/src/application_package.dart b/packages/flutter_tools/lib/src/application_package.dart
index b5a5bac43d..1b233b645e 100644
--- a/packages/flutter_tools/lib/src/application_package.dart
+++ b/packages/flutter_tools/lib/src/application_package.dart
@@ -8,7 +8,6 @@ import 'dart:io';
import 'package:path/path.dart' as path;
import 'package:xml/xml.dart' as xml;
-import 'artifacts.dart';
import 'build_configuration.dart';
import 'ios/plist_utils.dart';
@@ -36,32 +35,23 @@ abstract class ApplicationPackage {
}
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 = 'android/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'
final String launchActivity;
AndroidApk({
String localPath,
- String id: _defaultId,
- this.launchActivity: _defaultLaunchActivity
+ String id,
+ this.launchActivity
}) : 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))
+ factory AndroidApk.fromBuildConfiguration(BuildConfiguration config) {
+ String manifestPath = path.join('android', 'AndroidManifest.xml');
+ if (!FileSystemEntity.isFileSync(manifestPath))
return null;
- String manifestString = new File(manifest).readAsStringSync();
+ String manifestString = new File(manifestPath).readAsStringSync();
xml.XmlDocument document = xml.parse(manifestString);
Iterable manifests = document.findElements('manifest');
@@ -81,6 +71,7 @@ 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);
}
}
@@ -95,12 +86,12 @@ class IOSApp extends ApplicationPackage {
if (getCurrentHostPlatform() != HostPlatform.mac)
return null;
- String plistPath = path.join("ios", "Info.plist");
+ String plistPath = path.join('ios', 'Info.plist');
String value = getValueFromFile(plistPath, kCFBundleIdentifierKey);
if (value == null)
return null;
- String projectDir = path.join("ios", ".generated");
+ String projectDir = path.join('ios', '.generated');
return new IOSApp(iosProjectDir: projectDir, iosProjectBundleId: value);
}
@@ -134,20 +125,7 @@ class ApplicationPackageStore {
switch (config.targetPlatform) {
case TargetPlatform.android_arm:
assert(android == null);
- 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 {
- Artifact artifact = ArtifactStore.getArtifact(
- type: ArtifactType.shell, targetPlatform: TargetPlatform.android_arm);
- android = new AndroidApk(localPath: await ArtifactStore.getPath(artifact));
- }
+ android = new AndroidApk.fromBuildConfiguration(config);
break;
case TargetPlatform.ios_arm:
diff --git a/packages/flutter_tools/lib/src/artifacts.dart b/packages/flutter_tools/lib/src/artifacts.dart
index 19680d4fe0..db27a1961f 100644
--- a/packages/flutter_tools/lib/src/artifacts.dart
+++ b/packages/flutter_tools/lib/src/artifacts.dart
@@ -74,13 +74,7 @@ class Artifact {
class ArtifactStore {
static const List knownArtifacts = const [
const Artifact._(
- name: 'Sky Shell',
- fileName: 'SkyShell.apk',
- type: ArtifactType.shell,
- targetPlatform: TargetPlatform.android_arm
- ),
- const Artifact._(
- name: 'Sky Shell',
+ name: 'Flutter Tester',
fileName: 'sky_shell',
type: ArtifactType.shell,
targetPlatform: TargetPlatform.linux_x64
diff --git a/packages/flutter_tools/lib/src/commands/apk.dart b/packages/flutter_tools/lib/src/commands/apk.dart
index 43114e84c7..d6dc01be74 100644
--- a/packages/flutter_tools/lib/src/commands/apk.dart
+++ b/packages/flutter_tools/lib/src/commands/apk.dart
@@ -242,7 +242,7 @@ Future<_ApkComponents> _findApkComponents(
if (!components.resources.existsSync()) {
// TODO(eseidel): This level should be higher when path is manually set.
- printStatus('Can not locate Resources: ${components.resources}, ignoring.');
+ printStatus('Cannot locate Resources: ${components.resources}, ignoring.');
components.resources = null;
}
@@ -250,7 +250,7 @@ Future<_ApkComponents> _findApkComponents(
components.manifest, components.icuData, components.libSkyShell, components.debugKeystore
]..addAll(components.jars)) {
if (!f.existsSync()) {
- printError('Can not locate file: ${f.path}');
+ printError('Cannot locate file: ${f.path}');
return null;
}
}
@@ -453,8 +453,8 @@ Future build(
String target: ''
}) async {
if (!FileSystemEntity.isFileSync(_kDefaultAndroidManifestPath)) {
- printStatus('Using pre-built SkyShell.apk.');
- return 0;
+ printError('Cannot build APK. Missing $_kDefaultAndroidManifestPath.');
+ return 1;
}
int result = await buildAndroid(
diff --git a/packages/flutter_tools/lib/src/commands/run.dart b/packages/flutter_tools/lib/src/commands/run.dart
index 26c7dfc171..09f627e471 100644
--- a/packages/flutter_tools/lib/src/commands/run.dart
+++ b/packages/flutter_tools/lib/src/commands/run.dart
@@ -129,6 +129,18 @@ class RunCommand extends RunCommandBase {
}
}
+String _getMissingPackageHintForPlatform(TargetPlatform platform) {
+ switch (platform) {
+ case TargetPlatform.android_arm:
+ return 'Is your project missing an android/AndroidManifest.xml?';
+ case TargetPlatform.ios_arm:
+ case TargetPlatform.ios_x64:
+ return 'Is your project missing an ios/Info.plist?';
+ default:
+ return null;
+ }
+}
+
Future startApp(
Device device,
ApplicationPackageStore applicationPackages,
@@ -157,7 +169,11 @@ Future startApp(
ApplicationPackage package = applicationPackages.getPackageForPlatform(device.platform);
if (package == null) {
- printError('No application found for ${device.platform}.');
+ String message = 'No application found for ${device.platform}.';
+ String hint = _getMissingPackageHintForPlatform(device.platform);
+ if (hint != null)
+ message += '\n$hint';
+ printError(message);
return 1;
}
diff --git a/packages/flutter_tools/test/src/mocks.dart b/packages/flutter_tools/test/src/mocks.dart
index 62d6c369eb..52db59ea99 100644
--- a/packages/flutter_tools/test/src/mocks.dart
+++ b/packages/flutter_tools/test/src/mocks.dart
@@ -16,7 +16,11 @@ import 'package:mockito/mockito.dart';
class MockApplicationPackageStore extends ApplicationPackageStore {
MockApplicationPackageStore() : super(
- android: new AndroidApk(localPath: '/mock/path/to/android/SkyShell.apk'),
+ android: new AndroidApk(
+ localPath: '/mock/path/to/android/SkyShell.apk',
+ id: 'io.flutter.android.mock',
+ launchActivity: 'io.flutter.android.mock.MockActivity'
+ ),
iOS: new IOSApp(
iosProjectDir: '/mock/path/to/iOS/SkyShell.app',
iosProjectBundleId: 'io.flutter.ios.mock'