Unverified Commit e0ec9a06 authored by Jonah Williams's avatar Jonah Williams Committed by GitHub

[flutter_tools] Make ApplicationPackageFactory inject dependencies for Android Builds (#67827)

* [flutter_tools] simplication of application store logic

* maybe return null

* fix install tests

* Clean up imports

* revert windows test

* remove unused import
parent 6cfb86fb
...@@ -575,7 +575,8 @@ class AndroidDevice extends Device { ...@@ -575,7 +575,8 @@ class AndroidDevice extends Device {
); );
// Package has been built, so we can get the updated application ID and // Package has been built, so we can get the updated application ID and
// activity name from the .apk. // activity name from the .apk.
package = await AndroidApk.fromAndroidProject(project.android); package = await ApplicationPackageFactory.instance
.getPackageForPlatform(devicePlatform, buildInfo: debuggingOptions.buildInfo) as AndroidApk;
} }
// There was a failure parsing the android project information. // There was a failure parsing the android project information.
if (package == null) { if (package == null) {
......
...@@ -323,6 +323,7 @@ class AndroidSdk { ...@@ -323,6 +323,7 @@ class AndroidSdk {
sdkLevel: platformVersion, sdkLevel: platformVersion,
platformName: platformName, platformName: platformName,
buildToolsVersion: buildToolsVersion, buildToolsVersion: buildToolsVersion,
fileSystem: globals.fs,
); );
}).where((AndroidSdkVersion version) => version != null).toList(); }).where((AndroidSdkVersion version) => version != null).toList();
...@@ -436,19 +437,29 @@ class AndroidSdkVersion implements Comparable<AndroidSdkVersion> { ...@@ -436,19 +437,29 @@ class AndroidSdkVersion implements Comparable<AndroidSdkVersion> {
@required this.sdkLevel, @required this.sdkLevel,
@required this.platformName, @required this.platformName,
@required this.buildToolsVersion, @required this.buildToolsVersion,
@required FileSystem fileSystem,
}) : assert(sdkLevel != null), }) : assert(sdkLevel != null),
assert(platformName != null), assert(platformName != null),
assert(buildToolsVersion != null); assert(buildToolsVersion != null),
_fileSystem = fileSystem;
final AndroidSdk sdk; final AndroidSdk sdk;
final int sdkLevel; final int sdkLevel;
final String platformName; final String platformName;
final Version buildToolsVersion; final Version buildToolsVersion;
final FileSystem _fileSystem;
String get buildToolsVersionName => buildToolsVersion.toString(); String get buildToolsVersionName => buildToolsVersion.toString();
String get androidJarPath => getPlatformsPath('android.jar'); String get androidJarPath => getPlatformsPath('android.jar');
/// Return the path to the android application package tool.
///
/// This is used to dump the xml in order to launch built android applications.
///
/// See also:
/// * [AndroidApk.fromApk], which depends on this to determine application identifiers.
String get aaptPath => getBuildToolsPath('aapt'); String get aaptPath => getBuildToolsPath('aapt');
List<String> validateSdkWellFormed() { List<String> validateSdkWellFormed() {
...@@ -464,11 +475,11 @@ class AndroidSdkVersion implements Comparable<AndroidSdkVersion> { ...@@ -464,11 +475,11 @@ class AndroidSdkVersion implements Comparable<AndroidSdkVersion> {
} }
String getPlatformsPath(String itemName) { String getPlatformsPath(String itemName) {
return globals.fs.path.join(sdk.directory, 'platforms', platformName, itemName); return _fileSystem.path.join(sdk.directory, 'platforms', platformName, itemName);
} }
String getBuildToolsPath(String binaryName) { String getBuildToolsPath(String binaryName) {
return globals.fs.path.join(sdk.directory, 'build-tools', buildToolsVersionName, binaryName); return _fileSystem.path.join(sdk.directory, 'build-tools', buildToolsVersionName, binaryName);
} }
@override @override
...@@ -478,7 +489,7 @@ class AndroidSdkVersion implements Comparable<AndroidSdkVersion> { ...@@ -478,7 +489,7 @@ class AndroidSdkVersion implements Comparable<AndroidSdkVersion> {
String toString() => '[${sdk.directory}, SDK version $sdkLevel, build-tools $buildToolsVersionName]'; String toString() => '[${sdk.directory}, SDK version $sdkLevel, build-tools $buildToolsVersionName]';
String _exists(String path) { String _exists(String path) {
if (!globals.fs.isFileSync(path)) { if (!_fileSystem.isFileSync(path)) {
return 'Android SDK file not found: $path.'; return 'Android SDK file not found: $path.';
} }
return null; return null;
......
...@@ -5,13 +5,16 @@ ...@@ -5,13 +5,16 @@
import 'dart:collection'; import 'dart:collection';
import 'package:meta/meta.dart'; import 'package:meta/meta.dart';
import 'package:process/process.dart';
import 'package:xml/xml.dart'; import 'package:xml/xml.dart';
import 'android/android_sdk.dart';
import 'android/gradle.dart'; import 'android/gradle.dart';
import 'base/common.dart'; import 'base/common.dart';
import 'base/context.dart'; import 'base/context.dart';
import 'base/file_system.dart'; import 'base/file_system.dart';
import 'base/io.dart'; import 'base/io.dart';
import 'base/logger.dart';
import 'base/process.dart'; import 'base/process.dart';
import 'base/user_messages.dart'; import 'base/user_messages.dart';
import 'build_info.dart'; import 'build_info.dart';
...@@ -26,8 +29,28 @@ import 'web/web_device.dart'; ...@@ -26,8 +29,28 @@ import 'web/web_device.dart';
import 'windows/application_package.dart'; import 'windows/application_package.dart';
class ApplicationPackageFactory { class ApplicationPackageFactory {
ApplicationPackageFactory({
@required AndroidSdk androidSdk,
@required ProcessManager processManager,
@required Logger logger,
@required UserMessages userMessages,
@required FileSystem fileSystem,
}) : _androidSdk = androidSdk,
_processManager = processManager,
_logger = logger,
_userMessages = userMessages,
_fileSystem = fileSystem,
_processUtils = ProcessUtils(logger: logger, processManager: processManager);
static ApplicationPackageFactory get instance => context.get<ApplicationPackageFactory>(); static ApplicationPackageFactory get instance => context.get<ApplicationPackageFactory>();
final AndroidSdk _androidSdk;
final ProcessManager _processManager;
final Logger _logger;
final ProcessUtils _processUtils;
final UserMessages _userMessages;
final FileSystem _fileSystem;
Future<ApplicationPackage> getPackageForPlatform( Future<ApplicationPackage> getPackageForPlatform(
TargetPlatform platform, { TargetPlatform platform, {
BuildInfo buildInfo, BuildInfo buildInfo,
...@@ -39,12 +62,27 @@ class ApplicationPackageFactory { ...@@ -39,12 +62,27 @@ class ApplicationPackageFactory {
case TargetPlatform.android_arm64: case TargetPlatform.android_arm64:
case TargetPlatform.android_x64: case TargetPlatform.android_x64:
case TargetPlatform.android_x86: case TargetPlatform.android_x86:
if (globals.androidSdk?.licensesAvailable == true && globals.androidSdk?.latestVersion == null) { if (_androidSdk?.licensesAvailable == true && _androidSdk?.latestVersion == null) {
await checkGradleDependencies(); await checkGradleDependencies();
} }
return applicationBinary == null if (applicationBinary == null) {
? await AndroidApk.fromAndroidProject(FlutterProject.current().android) return await AndroidApk.fromAndroidProject(
: AndroidApk.fromApk(applicationBinary); FlutterProject.current().android,
processManager: _processManager,
processUtils: _processUtils,
logger: _logger,
androidSdk: _androidSdk,
userMessages: _userMessages,
fileSystem: _fileSystem,
);
}
return AndroidApk.fromApk(
applicationBinary,
processManager: _processManager,
logger: _logger,
androidSdk: _androidSdk,
userMessages: _userMessages,
);
case TargetPlatform.ios: case TargetPlatform.ios:
return applicationBinary == null return applicationBinary == null
? await IOSApp.fromIosProject(FlutterProject.current().ios, buildInfo) ? await IOSApp.fromIosProject(FlutterProject.current().ios, buildInfo)
...@@ -96,6 +134,7 @@ abstract class ApplicationPackage { ...@@ -96,6 +134,7 @@ abstract class ApplicationPackage {
String toString() => displayName ?? id; String toString() => displayName ?? id;
} }
/// An application package created from an already built Android APK.
class AndroidApk extends ApplicationPackage { class AndroidApk extends ApplicationPackage {
AndroidApk({ AndroidApk({
String id, String id,
...@@ -107,10 +146,17 @@ class AndroidApk extends ApplicationPackage { ...@@ -107,10 +146,17 @@ class AndroidApk extends ApplicationPackage {
super(id: id); super(id: id);
/// Creates a new AndroidApk from an existing APK. /// Creates a new AndroidApk from an existing APK.
factory AndroidApk.fromApk(File apk) { ///
final String aaptPath = globals.androidSdk?.latestVersion?.aaptPath; /// Returns `null` if the APK was invalid or any required tooling was missing.
if (aaptPath == null) { factory AndroidApk.fromApk(File apk, {
globals.printError(userMessages.aaptNotFound); @required AndroidSdk androidSdk,
@required ProcessManager processManager,
@required UserMessages userMessages,
@required Logger logger,
}) {
final String aaptPath = androidSdk?.latestVersion?.aaptPath;
if (aaptPath == null || !processManager.canRun(aaptPath)) {
logger.printError(userMessages.aaptNotFound);
return null; return null;
} }
...@@ -131,15 +177,15 @@ class AndroidApk extends ApplicationPackage { ...@@ -131,15 +177,15 @@ class AndroidApk extends ApplicationPackage {
return null; return null;
} }
final ApkManifestData data = ApkManifestData.parseFromXmlDump(apptStdout); final ApkManifestData data = ApkManifestData.parseFromXmlDump(apptStdout, logger);
if (data == null) { if (data == null) {
globals.printError('Unable to read manifest info from ${apk.path}.'); logger.printError('Unable to read manifest info from ${apk.path}.');
return null; return null;
} }
if (data.packageName == null || data.launchableActivityName == null) { if (data.packageName == null || data.launchableActivityName == null) {
globals.printError('Unable to read manifest info from ${apk.path}.'); logger.printError('Unable to read manifest info from ${apk.path}.');
return null; return null;
} }
...@@ -161,7 +207,14 @@ class AndroidApk extends ApplicationPackage { ...@@ -161,7 +207,14 @@ class AndroidApk extends ApplicationPackage {
final int versionCode; final int versionCode;
/// Creates a new AndroidApk based on the information in the Android manifest. /// Creates a new AndroidApk based on the information in the Android manifest.
static Future<AndroidApk> fromAndroidProject(AndroidProject androidProject) async { static Future<AndroidApk> fromAndroidProject(AndroidProject androidProject, {
@required AndroidSdk androidSdk,
@required ProcessManager processManager,
@required UserMessages userMessages,
@required ProcessUtils processUtils,
@required Logger logger,
@required FileSystem fileSystem,
}) async {
File apkFile; File apkFile;
if (androidProject.isUsingGradle) { if (androidProject.isUsingGradle) {
...@@ -169,20 +222,26 @@ class AndroidApk extends ApplicationPackage { ...@@ -169,20 +222,26 @@ class AndroidApk extends ApplicationPackage {
if (apkFile.existsSync()) { if (apkFile.existsSync()) {
// Grab information from the .apk. The gradle build script might alter // Grab information from the .apk. The gradle build script might alter
// the application Id, so we need to look at what was actually built. // the application Id, so we need to look at what was actually built.
return AndroidApk.fromApk(apkFile); return AndroidApk.fromApk(
apkFile,
androidSdk: androidSdk,
processManager: processManager,
logger: logger,
userMessages: userMessages,
);
} }
// The .apk hasn't been built yet, so we work with what we have. The run // The .apk hasn't been built yet, so we work with what we have. The run
// command will grab a new AndroidApk after building, to get the updated // command will grab a new AndroidApk after building, to get the updated
// IDs. // IDs.
} else { } else {
apkFile = globals.fs.file(globals.fs.path.join(getAndroidBuildDirectory(), 'app.apk')); apkFile = fileSystem.file(fileSystem.path.join(getAndroidBuildDirectory(), 'app.apk'));
} }
final File manifest = androidProject.appManifestFile; final File manifest = androidProject.appManifestFile;
if (!manifest.existsSync()) { if (!manifest.existsSync()) {
globals.printError('AndroidManifest.xml could not be found.'); logger.printError('AndroidManifest.xml could not be found.');
globals.printError('Please check ${manifest.path} for errors.'); logger.printError('Please check ${manifest.path} for errors.');
return null; return null;
} }
...@@ -193,19 +252,19 @@ class AndroidApk extends ApplicationPackage { ...@@ -193,19 +252,19 @@ class AndroidApk extends ApplicationPackage {
} on XmlParserException catch (exception) { } on XmlParserException catch (exception) {
String manifestLocation; String manifestLocation;
if (androidProject.isUsingGradle) { if (androidProject.isUsingGradle) {
manifestLocation = globals.fs.path.join(androidProject.hostAppGradleRoot.path, 'app', 'src', 'main', 'AndroidManifest.xml'); manifestLocation = fileSystem.path.join(androidProject.hostAppGradleRoot.path, 'app', 'src', 'main', 'AndroidManifest.xml');
} else { } else {
manifestLocation = globals.fs.path.join(androidProject.hostAppGradleRoot.path, 'AndroidManifest.xml'); manifestLocation = fileSystem.path.join(androidProject.hostAppGradleRoot.path, 'AndroidManifest.xml');
} }
globals.printError('AndroidManifest.xml is not a valid XML document.'); logger.printError('AndroidManifest.xml is not a valid XML document.');
globals.printError('Please check $manifestLocation for errors.'); logger.printError('Please check $manifestLocation for errors.');
throwToolExit('XML Parser error message: ${exception.toString()}'); throwToolExit('XML Parser error message: ${exception.toString()}');
} }
final Iterable<XmlElement> manifests = document.findElements('manifest'); final Iterable<XmlElement> manifests = document.findElements('manifest');
if (manifests.isEmpty) { if (manifests.isEmpty) {
globals.printError('AndroidManifest.xml has no manifest element.'); logger.printError('AndroidManifest.xml has no manifest element.');
globals.printError('Please check ${manifest.path} for errors.'); logger.printError('Please check ${manifest.path} for errors.');
return null; return null;
} }
final String packageId = manifests.first.getAttribute('package'); final String packageId = manifests.first.getAttribute('package');
...@@ -241,8 +300,8 @@ class AndroidApk extends ApplicationPackage { ...@@ -241,8 +300,8 @@ class AndroidApk extends ApplicationPackage {
} }
if (packageId == null || launchActivity == null) { if (packageId == null || launchActivity == null) {
globals.printError('package identifier or launch activity not found.'); logger.printError('package identifier or launch activity not found.');
globals.printError('Please check ${manifest.path} for errors.'); logger.printError('Please check ${manifest.path} for errors.');
return null; return null;
} }
...@@ -495,7 +554,7 @@ class ApkManifestData { ...@@ -495,7 +554,7 @@ class ApkManifestData {
return false; return false;
} }
static ApkManifestData parseFromXmlDump(String data) { static ApkManifestData parseFromXmlDump(String data, Logger logger) {
if (data == null || data.trim().isEmpty) { if (data == null || data.trim().isEmpty) {
return null; return null;
} }
...@@ -572,7 +631,7 @@ class ApkManifestData { ...@@ -572,7 +631,7 @@ class ApkManifestData {
final String packageName = package.value.substring(1, package.value.indexOf('" ')); final String packageName = package.value.substring(1, package.value.indexOf('" '));
if (launchActivity == null) { if (launchActivity == null) {
globals.printError('Error running $packageName. Default activity not found'); logger.printError('Error running $packageName. Default activity not found');
return null; return null;
} }
...@@ -584,16 +643,16 @@ class ApkManifestData { ...@@ -584,16 +643,16 @@ class ApkManifestData {
// Example format: (type 0x10)0x1 // Example format: (type 0x10)0x1
final _Attribute versionCodeAttr = manifest.firstAttribute('android:versionCode'); final _Attribute versionCodeAttr = manifest.firstAttribute('android:versionCode');
if (versionCodeAttr == null) { if (versionCodeAttr == null) {
globals.printError('Error running $packageName. Manifest versionCode not found'); logger.printError('Error running $packageName. Manifest versionCode not found');
return null; return null;
} }
if (!versionCodeAttr.value.startsWith('(type 0x10)')) { if (!versionCodeAttr.value.startsWith('(type 0x10)')) {
globals.printError('Error running $packageName. Manifest versionCode invalid'); logger.printError('Error running $packageName. Manifest versionCode invalid');
return null; return null;
} }
final int versionCode = int.tryParse(versionCodeAttr.value.substring(11)); final int versionCode = int.tryParse(versionCodeAttr.value.substring(11));
if (versionCode == null) { if (versionCode == null) {
globals.printError('Error running $packageName. Manifest versionCode invalid'); logger.printError('Error running $packageName. Manifest versionCode invalid');
return null; return null;
} }
......
...@@ -88,7 +88,13 @@ Future<T> runInContext<T>( ...@@ -88,7 +88,13 @@ Future<T> runInContext<T>(
androidSdk: globals.androidSdk, androidSdk: globals.androidSdk,
featureFlags: featureFlags, featureFlags: featureFlags,
), ),
ApplicationPackageFactory: () => ApplicationPackageFactory(), ApplicationPackageFactory: () => ApplicationPackageFactory(
userMessages: globals.userMessages,
processManager: globals.processManager,
logger: globals.logger,
fileSystem: globals.fs,
androidSdk: globals.androidSdk,
),
Artifacts: () => CachedArtifacts( Artifacts: () => CachedArtifacts(
fileSystem: globals.fs, fileSystem: globals.fs,
cache: globals.cache, cache: globals.cache,
......
...@@ -4,6 +4,7 @@ ...@@ -4,6 +4,7 @@
import 'package:file/file.dart'; import 'package:file/file.dart';
import 'package:flutter_tools/src/application_package.dart'; import 'package:flutter_tools/src/application_package.dart';
import 'package:flutter_tools/src/base/file_system.dart';
import 'package:flutter_tools/src/build_info.dart'; import 'package:flutter_tools/src/build_info.dart';
import 'package:flutter_tools/src/cache.dart'; import 'package:flutter_tools/src/cache.dart';
import 'package:flutter_tools/src/commands/install.dart'; import 'package:flutter_tools/src/commands/install.dart';
......
...@@ -10,8 +10,10 @@ import 'package:flutter_tools/src/android/android_sdk.dart'; ...@@ -10,8 +10,10 @@ import 'package:flutter_tools/src/android/android_sdk.dart';
import 'package:flutter_tools/src/application_package.dart'; import 'package:flutter_tools/src/application_package.dart';
import 'package:flutter_tools/src/base/context.dart'; import 'package:flutter_tools/src/base/context.dart';
import 'package:flutter_tools/src/base/file_system.dart'; import 'package:flutter_tools/src/base/file_system.dart';
import 'package:flutter_tools/src/base/logger.dart';
import 'package:flutter_tools/src/base/os.dart'; import 'package:flutter_tools/src/base/os.dart';
import 'package:flutter_tools/src/base/platform.dart'; import 'package:flutter_tools/src/base/platform.dart';
import 'package:flutter_tools/src/base/user_messages.dart';
import 'package:flutter_tools/src/build_info.dart'; import 'package:flutter_tools/src/build_info.dart';
import 'package:flutter_tools/src/cache.dart'; import 'package:flutter_tools/src/cache.dart';
import 'package:flutter_tools/src/fuchsia/application_package.dart'; import 'package:flutter_tools/src/fuchsia/application_package.dart';
...@@ -130,67 +132,114 @@ void main() { ...@@ -130,67 +132,114 @@ void main() {
expect(fakeProcessManager.hasRemainingExpectations, isFalse); expect(fakeProcessManager.hasRemainingExpectations, isFalse);
}, overrides: overrides); }, overrides: overrides);
testUsingContext('returns null when failed to extract manifest', () async { testWithoutContext('returns null when failed to extract manifest', () async {
final AndroidSdkVersion sdkVersion = MockitoAndroidSdkVersion(); final AndroidSdkVersion sdkVersion = MockitoAndroidSdkVersion();
when(sdk.latestVersion).thenReturn(sdkVersion); when(sdk.latestVersion).thenReturn(sdkVersion);
final AndroidApk androidApk = AndroidApk.fromApk(
null,
processManager: fakeProcessManager,
logger: BufferLogger.test(),
userMessages: UserMessages(),
androidSdk: sdk,
);
expect(AndroidApk.fromApk(null), isNull); expect(androidApk, isNull);
expect(fakeProcessManager.hasRemainingExpectations, isFalse); expect(fakeProcessManager.hasRemainingExpectations, isFalse);
}, overrides: overrides); });
}); });
group('ApkManifestData', () { group('ApkManifestData', () {
testUsingContext('Parses manifest with an Activity that has enabled set to true, action set to android.intent.action.MAIN and category set to android.intent.category.LAUNCHER', () { testWithoutContext('Parses manifest with an Activity that has enabled set to true, action set to android.intent.action.MAIN and category set to android.intent.category.LAUNCHER', () {
final ApkManifestData data = ApkManifestData.parseFromXmlDump(_aaptDataWithExplicitEnabledAndMainLauncherActivity); final ApkManifestData data = ApkManifestData.parseFromXmlDump(
_aaptDataWithExplicitEnabledAndMainLauncherActivity,
BufferLogger.test(),
);
expect(data, isNotNull); expect(data, isNotNull);
expect(data.packageName, 'io.flutter.examples.hello_world'); expect(data.packageName, 'io.flutter.examples.hello_world');
expect(data.launchableActivityName, 'io.flutter.examples.hello_world.MainActivity2'); expect(data.launchableActivityName, 'io.flutter.examples.hello_world.MainActivity2');
}, overrides: noColorTerminalOverride); });
testWithoutContext('Parses manifest with an Activity that has no value for its enabled field, action set to android.intent.action.MAIN and category set to android.intent.category.LAUNCHER', () {
final ApkManifestData data = ApkManifestData.parseFromXmlDump(
_aaptDataWithDefaultEnabledAndMainLauncherActivity,
BufferLogger.test(),
);
testUsingContext('Parses manifest with an Activity that has no value for its enabled field, action set to android.intent.action.MAIN and category set to android.intent.category.LAUNCHER', () {
final ApkManifestData data = ApkManifestData.parseFromXmlDump(_aaptDataWithDefaultEnabledAndMainLauncherActivity);
expect(data, isNotNull); expect(data, isNotNull);
expect(data.packageName, 'io.flutter.examples.hello_world'); expect(data.packageName, 'io.flutter.examples.hello_world');
expect(data.launchableActivityName, 'io.flutter.examples.hello_world.MainActivity2'); expect(data.launchableActivityName, 'io.flutter.examples.hello_world.MainActivity2');
}, overrides: noColorTerminalOverride); });
testWithoutContext('Parses manifest with a dist namespace', () {
final ApkManifestData data = ApkManifestData.parseFromXmlDump(
_aaptDataWithDistNamespace,
BufferLogger.test(),
);
testUsingContext('Parses manifest with a dist namespace', () {
final ApkManifestData data = ApkManifestData.parseFromXmlDump(_aaptDataWithDistNamespace);
expect(data, isNotNull); expect(data, isNotNull);
expect(data.packageName, 'io.flutter.examples.hello_world'); expect(data.packageName, 'io.flutter.examples.hello_world');
expect(data.launchableActivityName, 'io.flutter.examples.hello_world.MainActivity'); expect(data.launchableActivityName, 'io.flutter.examples.hello_world.MainActivity');
}, overrides: noColorTerminalOverride); });
testWithoutContext('Error when parsing manifest with no Activity that has enabled set to true nor has no value for its enabled field', () {
final BufferLogger logger = BufferLogger.test();
final ApkManifestData data = ApkManifestData.parseFromXmlDump(
_aaptDataWithNoEnabledActivity,
logger,
);
testUsingContext('Error when parsing manifest with no Activity that has enabled set to true nor has no value for its enabled field', () {
final ApkManifestData data = ApkManifestData.parseFromXmlDump(_aaptDataWithNoEnabledActivity);
expect(data, isNull); expect(data, isNull);
expect( expect(
testLogger.errorText, 'Error running io.flutter.examples.hello_world. Default activity not found\n'); logger.errorText,
}, overrides: noColorTerminalOverride); 'Error running io.flutter.examples.hello_world. Default activity not found\n',
);
});
testWithoutContext('Error when parsing manifest with no Activity that has action set to android.intent.action.MAIN', () {
final BufferLogger logger = BufferLogger.test();
final ApkManifestData data = ApkManifestData.parseFromXmlDump(
_aaptDataWithNoMainActivity,
logger,
);
testUsingContext('Error when parsing manifest with no Activity that has action set to android.intent.action.MAIN', () {
final ApkManifestData data = ApkManifestData.parseFromXmlDump(_aaptDataWithNoMainActivity);
expect(data, isNull); expect(data, isNull);
expect( expect(
testLogger.errorText, 'Error running io.flutter.examples.hello_world. Default activity not found\n'); logger.errorText,
}, overrides: noColorTerminalOverride); 'Error running io.flutter.examples.hello_world. Default activity not found\n',
);
});
testWithoutContext('Error when parsing manifest with no Activity that has category set to android.intent.category.LAUNCHER', () {
final BufferLogger logger = BufferLogger.test();
final ApkManifestData data = ApkManifestData.parseFromXmlDump(
_aaptDataWithNoLauncherActivity,
logger,
);
testUsingContext('Error when parsing manifest with no Activity that has category set to android.intent.category.LAUNCHER', () {
final ApkManifestData data = ApkManifestData.parseFromXmlDump(_aaptDataWithNoLauncherActivity);
expect(data, isNull); expect(data, isNull);
expect( expect(
testLogger.errorText, 'Error running io.flutter.examples.hello_world. Default activity not found\n'); logger.errorText,
}, overrides: noColorTerminalOverride); 'Error running io.flutter.examples.hello_world. Default activity not found\n',
);
});
testWithoutContext('Parsing manifest with Activity that has multiple category, android.intent.category.LAUNCHER and android.intent.category.DEFAULT', () {
final ApkManifestData data = ApkManifestData.parseFromXmlDump(
_aaptDataWithLauncherAndDefaultActivity,
BufferLogger.test(),
);
testUsingContext('Parsing manifest with Activity that has multiple category, android.intent.category.LAUNCHER and android.intent.category.DEFAULT', () {
final ApkManifestData data = ApkManifestData.parseFromXmlDump(_aaptDataWithLauncherAndDefaultActivity);
expect(data, isNotNull); expect(data, isNotNull);
expect(data.packageName, 'io.flutter.examples.hello_world'); expect(data.packageName, 'io.flutter.examples.hello_world');
expect(data.launchableActivityName, 'io.flutter.examples.hello_world.MainActivity'); expect(data.launchableActivityName, 'io.flutter.examples.hello_world.MainActivity');
}, overrides: noColorTerminalOverride); });
testUsingContext('Parses manifest with missing application tag', () async { testWithoutContext('Parses manifest with missing application tag', () async {
final ApkManifestData data = ApkManifestData.parseFromXmlDump(_aaptDataWithoutApplication); final ApkManifestData data = ApkManifestData.parseFromXmlDump(
_aaptDataWithoutApplication,
BufferLogger.test(),
);
expect(data, isNull); expect(data, isNull);
}); });
......
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