Skip to content

Commit

Permalink
Revert "[flutter_tools] use new output location for the apk (#54328)"
Browse files Browse the repository at this point in the history
This reverts commit 9cb9bfb.
  • Loading branch information
jonahwilliams committed Apr 13, 2020
1 parent db36d3b commit 1482995
Show file tree
Hide file tree
Showing 2 changed files with 122 additions and 82 deletions.
70 changes: 15 additions & 55 deletions packages/flutter_tools/lib/src/android/gradle.dart
Expand Up @@ -39,7 +39,7 @@ Directory getApkDirectory(FlutterProject project) {
: project.android.buildDirectory
.childDirectory('app')
.childDirectory('outputs')
.childDirectory('flutter-apk');
.childDirectory('apk');
}

/// The directory where the app bundle artifact is generated.
Expand Down Expand Up @@ -469,33 +469,25 @@ Future<void> buildGradleApp({
return;
}
// Gradle produced an APK.
final Iterable<String> apkFilesPaths = project.isModule
? findApkFilesModule(project, androidBuildInfo)
: listApkPaths(androidBuildInfo);
final Iterable<File> apkFiles = findApkFiles(project, androidBuildInfo);
final Directory apkDirectory = getApkDirectory(project);
final File apkFile = apkDirectory.childFile(apkFilesPaths.first);
if (!apkFile.existsSync()) {
_exitWithExpectedFileNotFound(
project: project,
fileExtension: '.apk',
);
}

// Copy the first APK to app.apk, so `flutter run` can find it.
// TODO(egarciad): Handle multiple APKs.
apkFile.copySync(apkDirectory.childFile('app.apk').path);
apkFiles.first.copySync(apkDirectory.childFile('app.apk').path);
globals.printTrace('calculateSha: $apkDirectory/app.apk');

final File apkShaFile = apkDirectory.childFile('app.apk.sha1');
apkShaFile.writeAsStringSync(_calculateSha(apkFile));
apkShaFile.writeAsStringSync(_calculateSha(apkFiles.first));

final String appSize = (buildInfo.mode == BuildMode.debug)
? '' // Don't display the size when building a debug variant.
: ' (${getSizeAsMB(apkFile.lengthSync())})';
globals.printStatus(
'$successMark Built ${globals.fs.path.relative(apkFile.path)}$appSize.',
color: TerminalColor.green,
);
for (final File apkFile in apkFiles) {
final String appSize = (buildInfo.mode == BuildMode.debug)
? '' // Don't display the size when building a debug variant.
: ' (${getSizeAsMB(apkFile.lengthSync())})';
globals.printStatus(
'$successMark Built ${globals.fs.path.relative(apkFile.path)}$appSize.',
color: TerminalColor.green,
);
}
}

/// Builds AAR and POM files.
Expand Down Expand Up @@ -786,7 +778,7 @@ Future<void> buildPluginsAsAar(

/// Returns the APK files for a given [FlutterProject] and [AndroidBuildInfo].
@visibleForTesting
Iterable<String> findApkFilesModule(
Iterable<File> findApkFiles(
FlutterProject project,
AndroidBuildInfo androidBuildInfo,
) {
Expand Down Expand Up @@ -823,39 +815,7 @@ Iterable<String> findApkFilesModule(
fileExtension: '.apk',
);
}
return apks.map((File file) => file.path);
}

/// Returns the APK files for a given [FlutterProject] and [AndroidBuildInfo].
///
/// The flutter.gradle plugin will copy APK outputs into:
/// $buildDir/app/outputs/flutter-apk/app-<abi>-<flavor-flag>-<build-mode-flag>.apk
@visibleForTesting
Iterable<String> listApkPaths(
AndroidBuildInfo androidBuildInfo,
) {
final String buildType = camelCase(androidBuildInfo.buildInfo.modeName);
final List<String> apkPartialName = <String>[
if (androidBuildInfo.buildInfo.flavor?.isNotEmpty ?? false)
androidBuildInfo.buildInfo.flavor,
'$buildType.apk',
];
if (androidBuildInfo.splitPerAbi) {
return <String>[
for (AndroidArch androidArch in androidBuildInfo.targetArchs)
<String>[
'app',
getNameForAndroidArch(androidArch),
...apkPartialName
].join('-')
];
}
return <String>[
<String>[
'app',
...apkPartialName,
].join('-')
];
return apks;
}

@visibleForTesting
Expand Down
134 changes: 107 additions & 27 deletions packages/flutter_tools/test/general.shard/android/gradle_test.dart
Expand Up @@ -44,7 +44,7 @@ void main() {

expect(
getApkDirectory(project).path,
equals(globals.fs.path.join('foo', 'app', 'outputs', 'flutter-apk')),
equals(globals.fs.path.join('foo', 'app', 'outputs', 'apk')),
);
});

Expand Down Expand Up @@ -312,41 +312,107 @@ void main() {
});
});

group('listApkPaths', () {
testWithoutContext('Finds APK without flavor in release', () {
final Iterable<String> apks = listApkPaths(
group('findApkFiles', () {
final Usage mockUsage = MockUsage();

testUsingContext('Finds APK without flavor in release', () {
final FlutterProject project = MockFlutterProject();
final AndroidProject androidProject = MockAndroidProject();

when(project.android).thenReturn(androidProject);
when(project.isModule).thenReturn(false);
when(androidProject.buildDirectory).thenReturn(globals.fs.directory('irrelevant'));

final Directory apkDirectory = globals.fs.directory(globals.fs.path.join('irrelevant', 'app', 'outputs', 'apk', 'release'));
apkDirectory.createSync(recursive: true);
apkDirectory.childFile('app-release.apk').createSync();

final Iterable<File> apks = findApkFiles(
project,
const AndroidBuildInfo(BuildInfo(BuildMode.release, '', treeShakeIcons: false)),
);

expect(apks, <String>['app-release.apk']);
expect(apks.isNotEmpty, isTrue);
expect(apks.first.path, equals(globals.fs.path.join('irrelevant', 'app', 'outputs', 'apk', 'release', 'app-release.apk')));
}, overrides: <Type, Generator>{
FileSystem: () => MemoryFileSystem(),
ProcessManager: () => FakeProcessManager.any(),
});

testWithoutContext('Finds APK with flavor in release mode', () {
final Iterable<String> apks = listApkPaths(
testUsingContext('Finds APK with flavor in release mode', () {
final FlutterProject project = MockFlutterProject();
final AndroidProject androidProject = MockAndroidProject();

when(project.android).thenReturn(androidProject);
when(project.isModule).thenReturn(false);
when(androidProject.buildDirectory).thenReturn(globals.fs.directory('irrelevant'));

final Directory apkDirectory = globals.fs.directory(globals.fs.path.join('irrelevant', 'app', 'outputs', 'apk', 'release'));
apkDirectory.createSync(recursive: true);
apkDirectory.childFile('app-flavor1-release.apk').createSync();

final Iterable<File> apks = findApkFiles(
project,
const AndroidBuildInfo(BuildInfo(BuildMode.release, 'flavor1', treeShakeIcons: false)),
);

expect(apks, <String>['app-flavor1-release.apk']);
expect(apks.isNotEmpty, isTrue);
expect(apks.first.path, equals(globals.fs.path.join('irrelevant', 'app', 'outputs', 'apk', 'release', 'app-flavor1-release.apk')));
}, overrides: <Type, Generator>{
FileSystem: () => MemoryFileSystem(),
ProcessManager: () => FakeProcessManager.any(),
});

testWithoutContext('Finds APK with flavor in release mode - AGP v3', () {
final Iterable<String> apks = listApkPaths(
testUsingContext('Finds APK with flavor in release mode - AGP v3', () {
final FlutterProject project = MockFlutterProject();
final AndroidProject androidProject = MockAndroidProject();

when(project.android).thenReturn(androidProject);
when(project.isModule).thenReturn(false);
when(androidProject.buildDirectory).thenReturn(globals.fs.directory('irrelevant'));

final Directory apkDirectory = globals.fs.directory(globals.fs.path.join('irrelevant', 'app', 'outputs', 'apk', 'flavor1', 'release'));
apkDirectory.createSync(recursive: true);
apkDirectory.childFile('app-flavor1-release.apk').createSync();

final Iterable<File> apks = findApkFiles(
project,
const AndroidBuildInfo(BuildInfo(BuildMode.release, 'flavor1', treeShakeIcons: false)),
);

expect(apks, <String>['app-flavor1-release.apk']);
expect(apks.isNotEmpty, isTrue);
expect(apks.first.path, equals(globals.fs.path.join('irrelevant', 'app', 'outputs', 'apk', 'flavor1', 'release', 'app-flavor1-release.apk')));
}, overrides: <Type, Generator>{
FileSystem: () => MemoryFileSystem(),
ProcessManager: () => FakeProcessManager.any(),
});

testWithoutContext('Finds APK with split-per-abi', () {
final Iterable<String> apks = listApkPaths(
const AndroidBuildInfo(BuildInfo(BuildMode.release, 'flavor1', treeShakeIcons: false), splitPerAbi: true),
testUsingContext('apk not found', () {
final FlutterProject project = FlutterProject.current();
expect(
() {
findApkFiles(
project,
const AndroidBuildInfo(BuildInfo(BuildMode.debug, 'foo_bar', treeShakeIcons: false)),
);
},
throwsToolExit(
message:
"Gradle build failed to produce an .apk file. It's likely that this file "
"was generated under ${project.android.buildDirectory.path}, but the tool couldn't find it."
)
);

expect(apks, unorderedEquals(<String>[
'app-armeabi-v7a-flavor1-release.apk',
'app-arm64-v8a-flavor1-release.apk',
'app-x86_64-flavor1-release.apk',
]));
verify(
mockUsage.sendEvent(
any,
any,
label: 'gradle-expected-file-not-found',
parameters: const <String, String> {
'cd37': 'androidGradlePluginVersion: 5.6.2, fileExtension: .apk',
},
),
).called(1);
}, overrides: <Type, Generator>{
FileSystem: () => MemoryFileSystem(),
ProcessManager: () => FakeProcessManager.any(),
Usage: () => mockUsage,
});
});

Expand Down Expand Up @@ -1349,7 +1415,8 @@ plugin1=${plugin1.path}
fileSystem.directory('build')
.childDirectory('app')
.childDirectory('outputs')
.childDirectory('flutter-apk')
.childDirectory('apk')
.childDirectory('release')
.childFile('app-release.apk')
.createSync(recursive: true);

Expand Down Expand Up @@ -1388,6 +1455,7 @@ plugin1=${plugin1.path}
label: 'gradle-random-event-label-success',
parameters: anyNamed('parameters'),
)).called(1);

}, overrides: <Type, Generator>{
AndroidSdk: () => mockAndroidSdk,
Cache: () => cache,
Expand Down Expand Up @@ -1485,6 +1553,17 @@ plugin1=${plugin1.path}
});

testUsingContext('indicates that an APK has been built successfully', () async {
when(mockProcessManager.start(any,
workingDirectory: anyNamed('workingDirectory'),
environment: anyNamed('environment')))
.thenAnswer((_) {
return Future<Process>.value(
createMockProcess(
exitCode: 0,
stdout: '',
));
});

fileSystem.directory('android')
.childFile('build.gradle')
.createSync(recursive: true);
Expand All @@ -1502,7 +1581,8 @@ plugin1=${plugin1.path}
fileSystem.directory('build')
.childDirectory('app')
.childDirectory('outputs')
.childDirectory('flutter-apk')
.childDirectory('apk')
.childDirectory('release')
.childFile('app-release.apk')
.createSync(recursive: true);

Expand All @@ -1522,15 +1602,15 @@ plugin1=${plugin1.path}

expect(
testLogger.statusText,
contains('Built build/app/outputs/flutter-apk/app-release.apk (0.0MB)'),
contains('Built build/app/outputs/apk/release/app-release.apk (0.0MB)'),
);

}, overrides: <Type, Generator>{
AndroidSdk: () => mockAndroidSdk,
Cache: () => cache,
FileSystem: () => fileSystem,
Platform: () => android,
ProcessManager: () => FakeProcessManager.any(),
ProcessManager: () => mockProcessManager,
});

testUsingContext("doesn't indicate how to consume an AAR when printHowToConsumeAaar is false", () async {
Expand Down

0 comments on commit 1482995

Please sign in to comment.