Unverified Commit 3d94b8fd authored by Alex Li's avatar Alex Li Committed by GitHub

[tool] Install the corresponding APK in `flutter run` (#113622)

parent 1b4b99b4
...@@ -114,8 +114,8 @@ void main() { ...@@ -114,8 +114,8 @@ void main() {
_findNextMatcherInList( _findNextMatcherInList(
stdout, stdout,
(String line) => line.startsWith('Installing build/app/outputs/flutter-apk/app.apk...'), (String line) => line.startsWith('Installing build/app/outputs/flutter-apk/app-release.apk...'),
'Installing build/app/outputs/flutter-apk/app.apk...', 'Installing build/app/outputs/flutter-apk/app-release.apk...',
); );
_findNextMatcherInList( _findNextMatcherInList(
......
...@@ -103,11 +103,20 @@ class AndroidApk extends ApplicationPackage implements PrebuiltApplicationPackag ...@@ -103,11 +103,20 @@ class AndroidApk extends ApplicationPackage implements PrebuiltApplicationPackag
required ProcessUtils processUtils, required ProcessUtils processUtils,
required Logger logger, required Logger logger,
required FileSystem fileSystem, required FileSystem fileSystem,
BuildInfo? buildInfo,
}) async { }) async {
File apkFile; final File apkFile;
final String filename;
if (buildInfo == null) {
filename = 'app.apk';
} else if (buildInfo.flavor == null) {
filename = 'app-${buildInfo.mode.name}.apk';
} else {
filename = 'app-${buildInfo.lowerCasedFlavor}-${buildInfo.mode.name}.apk';
}
if (androidProject.isUsingGradle && androidProject.isSupportedVersion) { if (androidProject.isUsingGradle && androidProject.isSupportedVersion) {
apkFile = getApkDirectory(androidProject.parent).childFile('app.apk'); apkFile = getApkDirectory(androidProject.parent).childFile(filename);
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.
...@@ -124,7 +133,7 @@ class AndroidApk extends ApplicationPackage implements PrebuiltApplicationPackag ...@@ -124,7 +133,7 @@ class AndroidApk extends ApplicationPackage implements PrebuiltApplicationPackag
// 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 = fileSystem.file(fileSystem.path.join(getAndroidBuildDirectory(), 'app.apk')); apkFile = fileSystem.file(fileSystem.path.join(getAndroidBuildDirectory(), filename));
} }
final File manifest = androidProject.appManifestFile; final File manifest = androidProject.appManifestFile;
......
...@@ -465,12 +465,14 @@ class AndroidGradleBuilder implements AndroidBuilder { ...@@ -465,12 +465,14 @@ class AndroidGradleBuilder implements AndroidBuilder {
); );
return; return;
} }
// Gradle produced an APK. // Gradle produced APKs.
final Iterable<String> apkFilesPaths = project.isModule final Iterable<String> apkFilesPaths = project.isModule
? findApkFilesModule(project, androidBuildInfo, _logger, _usage) ? findApkFilesModule(project, androidBuildInfo, _logger, _usage)
: listApkPaths(androidBuildInfo); : listApkPaths(androidBuildInfo);
final Directory apkDirectory = getApkDirectory(project); final Directory apkDirectory = getApkDirectory(project);
final File apkFile = apkDirectory.childFile(apkFilesPaths.first);
// Generate sha1 for every generated APKs.
for (final File apkFile in apkFilesPaths.map(apkDirectory.childFile)) {
if (!apkFile.existsSync()) { if (!apkFile.existsSync()) {
_exitWithExpectedFileNotFound( _exitWithExpectedFileNotFound(
project: project, project: project,
...@@ -480,14 +482,9 @@ class AndroidGradleBuilder implements AndroidBuilder { ...@@ -480,14 +482,9 @@ class AndroidGradleBuilder implements AndroidBuilder {
); );
} }
// Copy the first APK to app.apk, so `flutter run` can find it. final String filename = apkFile.basename;
// TODO(egarciad): Handle multiple APKs. _logger.printTrace('Calculate SHA1: $apkDirectory/$filename');
apkFile.copySync(apkDirectory final File apkShaFile = apkDirectory.childFile('$filename.sha1');
.childFile('app.apk')
.path);
_logger.printTrace('calculateSha: $apkDirectory/app.apk');
final File apkShaFile = apkDirectory.childFile('app.apk.sha1');
apkShaFile.writeAsStringSync(_calculateSha(apkFile)); apkShaFile.writeAsStringSync(_calculateSha(apkFile));
final String appSize = (buildInfo.mode == BuildMode.debug) final String appSize = (buildInfo.mode == BuildMode.debug)
...@@ -502,6 +499,7 @@ class AndroidGradleBuilder implements AndroidBuilder { ...@@ -502,6 +499,7 @@ class AndroidGradleBuilder implements AndroidBuilder {
await _performCodeSizeAnalysis('apk', apkFile, androidBuildInfo); await _performCodeSizeAnalysis('apk', apkFile, androidBuildInfo);
} }
} }
}
Future<void> _performCodeSizeAnalysis(String kind, Future<void> _performCodeSizeAnalysis(String kind,
File zipFile, File zipFile,
......
...@@ -66,6 +66,7 @@ class FlutterApplicationPackageFactory extends ApplicationPackageFactory { ...@@ -66,6 +66,7 @@ class FlutterApplicationPackageFactory extends ApplicationPackageFactory {
androidSdk: _androidSdk, androidSdk: _androidSdk,
userMessages: _userMessages, userMessages: _userMessages,
fileSystem: _fileSystem, fileSystem: _fileSystem,
buildInfo: buildInfo,
); );
} }
return AndroidApk.fromApk( return AndroidApk.fromApk(
......
...@@ -65,7 +65,7 @@ void main() { ...@@ -65,7 +65,7 @@ void main() {
platform: FakePlatform(), platform: FakePlatform(),
androidSdk: androidSdk, androidSdk: androidSdk,
); );
final File apkFile = fileSystem.file('app.apk')..createSync(); final File apkFile = fileSystem.file('app-debug.apk')..createSync();
final AndroidApk apk = AndroidApk( final AndroidApk apk = AndroidApk(
id: 'FlutterApp', id: 'FlutterApp',
applicationPackage: apkFile, applicationPackage: apkFile,
...@@ -88,7 +88,7 @@ void main() { ...@@ -88,7 +88,7 @@ void main() {
command: <String>['adb', '-s', '1234', 'shell', 'pm', 'list', 'packages', 'FlutterApp'], command: <String>['adb', '-s', '1234', 'shell', 'pm', 'list', 'packages', 'FlutterApp'],
)); ));
processManager.addCommand(const FakeCommand( processManager.addCommand(const FakeCommand(
command: <String>['adb', '-s', '1234', 'install', '-t', '-r', 'app.apk'], command: <String>['adb', '-s', '1234', 'install', '-t', '-r', 'app-debug.apk'],
)); ));
processManager.addCommand(kShaCommand); processManager.addCommand(kShaCommand);
processManager.addCommand(const FakeCommand( processManager.addCommand(const FakeCommand(
...@@ -132,7 +132,7 @@ void main() { ...@@ -132,7 +132,7 @@ void main() {
platform: FakePlatform(), platform: FakePlatform(),
androidSdk: androidSdk, androidSdk: androidSdk,
); );
final File apkFile = fileSystem.file('app.apk')..createSync(); final File apkFile = fileSystem.file('app-debug.apk')..createSync();
final AndroidApk apk = AndroidApk( final AndroidApk apk = AndroidApk(
id: 'FlutterApp', id: 'FlutterApp',
applicationPackage: apkFile, applicationPackage: apkFile,
...@@ -170,7 +170,7 @@ void main() { ...@@ -170,7 +170,7 @@ void main() {
platform: FakePlatform(), platform: FakePlatform(),
androidSdk: androidSdk, androidSdk: androidSdk,
); );
final File apkFile = fileSystem.file('app.apk')..createSync(); final File apkFile = fileSystem.file('app-debug.apk')..createSync();
final AndroidApk apk = AndroidApk( final AndroidApk apk = AndroidApk(
id: 'FlutterApp', id: 'FlutterApp',
applicationPackage: apkFile, applicationPackage: apkFile,
...@@ -200,7 +200,7 @@ void main() { ...@@ -200,7 +200,7 @@ void main() {
'-r', '-r',
'--user', '--user',
'10', '10',
'app.apk', 'app-debug.apk',
], ],
stdout: '\n\nThe Dart VM service is listening on http://127.0.0.1:456\n\n', stdout: '\n\nThe Dart VM service is listening on http://127.0.0.1:456\n\n',
)); ));
......
...@@ -31,7 +31,7 @@ const FakeCommand kInstallCommand = FakeCommand( ...@@ -31,7 +31,7 @@ const FakeCommand kInstallCommand = FakeCommand(
'-r', '-r',
'--user', '--user',
'10', '10',
'app.apk', 'app-debug.apk',
], ],
); );
const FakeCommand kStoreShaCommand = FakeCommand( const FakeCommand kStoreShaCommand = FakeCommand(
...@@ -71,7 +71,7 @@ void main() { ...@@ -71,7 +71,7 @@ void main() {
stdout: '[ro.build.version.sdk]: [11]', stdout: '[ro.build.version.sdk]: [11]',
), ),
]); ]);
final File apk = fileSystem.file('app.apk')..createSync(); final File apk = fileSystem.file('app-debug.apk')..createSync();
final AndroidApk androidApk = AndroidApk( final AndroidApk androidApk = AndroidApk(
applicationPackage: apk, applicationPackage: apk,
id: 'app', id: 'app',
...@@ -87,7 +87,7 @@ void main() { ...@@ -87,7 +87,7 @@ void main() {
}); });
testWithoutContext('Cannot install app if APK file is missing', () async { testWithoutContext('Cannot install app if APK file is missing', () async {
final File apk = fileSystem.file('app.apk'); final File apk = fileSystem.file('app-debug.apk');
final AndroidApk androidApk = AndroidApk( final AndroidApk androidApk = AndroidApk(
applicationPackage: apk, applicationPackage: apk,
id: 'app', id: 'app',
...@@ -115,7 +115,7 @@ void main() { ...@@ -115,7 +115,7 @@ void main() {
kInstallCommand, kInstallCommand,
kStoreShaCommand, kStoreShaCommand,
]); ]);
final File apk = fileSystem.file('app.apk')..createSync(); final File apk = fileSystem.file('app-debug.apk')..createSync();
final AndroidApk androidApk = AndroidApk( final AndroidApk androidApk = AndroidApk(
applicationPackage: apk, applicationPackage: apk,
id: 'app', id: 'app',
...@@ -144,7 +144,7 @@ void main() { ...@@ -144,7 +144,7 @@ void main() {
kInstallCommand, kInstallCommand,
kStoreShaCommand, kStoreShaCommand,
]); ]);
final File apk = fileSystem.file('app.apk')..createSync(); final File apk = fileSystem.file('app-debug.apk')..createSync();
final AndroidApk androidApk = AndroidApk( final AndroidApk androidApk = AndroidApk(
applicationPackage: apk, applicationPackage: apk,
id: 'app', id: 'app',
...@@ -182,13 +182,13 @@ void main() { ...@@ -182,13 +182,13 @@ void main() {
'-r', '-r',
'--user', '--user',
'jane', 'jane',
'app.apk', 'app-debug.apk',
], ],
exitCode: 1, exitCode: 1,
stderr: 'Exception occurred while executing: java.lang.IllegalArgumentException: Bad user number: jane', stderr: 'Exception occurred while executing: java.lang.IllegalArgumentException: Bad user number: jane',
), ),
]); ]);
final File apk = fileSystem.file('app.apk')..createSync(); final File apk = fileSystem.file('app-debug.apk')..createSync();
final AndroidApk androidApk = AndroidApk( final AndroidApk androidApk = AndroidApk(
applicationPackage: apk, applicationPackage: apk,
id: 'app', id: 'app',
...@@ -221,8 +221,8 @@ void main() { ...@@ -221,8 +221,8 @@ void main() {
stdout: 'example_sha', stdout: 'example_sha',
), ),
]); ]);
final File apk = fileSystem.file('app.apk')..createSync(); final File apk = fileSystem.file('app-debug.apk')..createSync();
fileSystem.file('app.apk.sha1').writeAsStringSync('example_sha'); fileSystem.file('app-debug.apk.sha1').writeAsStringSync('example_sha');
final AndroidApk androidApk = AndroidApk( final AndroidApk androidApk = AndroidApk(
applicationPackage: apk, applicationPackage: apk,
id: 'app', id: 'app',
...@@ -254,7 +254,7 @@ void main() { ...@@ -254,7 +254,7 @@ void main() {
stdout: 'different_example_sha', stdout: 'different_example_sha',
), ),
const FakeCommand( const FakeCommand(
command: <String>['adb', '-s', '1234', 'install', '-t', '-r', '--user', '10', 'app.apk'], command: <String>['adb', '-s', '1234', 'install', '-t', '-r', '--user', '10', 'app-debug.apk'],
exitCode: 1, exitCode: 1,
stderr: '[INSTALL_FAILED_INSUFFICIENT_STORAGE]', stderr: '[INSTALL_FAILED_INSUFFICIENT_STORAGE]',
), ),
...@@ -262,8 +262,8 @@ void main() { ...@@ -262,8 +262,8 @@ void main() {
kInstallCommand, kInstallCommand,
const FakeCommand(command: <String>['adb', '-s', '1234', 'shell', 'echo', '-n', 'example_sha', '>', '/data/local/tmp/sky.app.sha1']), const FakeCommand(command: <String>['adb', '-s', '1234', 'shell', 'echo', '-n', 'example_sha', '>', '/data/local/tmp/sky.app.sha1']),
]); ]);
final File apk = fileSystem.file('app.apk')..createSync(); final File apk = fileSystem.file('app-debug.apk')..createSync();
fileSystem.file('app.apk.sha1').writeAsStringSync('example_sha'); fileSystem.file('app-debug.apk.sha1').writeAsStringSync('example_sha');
final AndroidApk androidApk = AndroidApk( final AndroidApk androidApk = AndroidApk(
applicationPackage: apk, applicationPackage: apk,
id: 'app', id: 'app',
...@@ -291,12 +291,12 @@ void main() { ...@@ -291,12 +291,12 @@ void main() {
stdout: '\n' stdout: '\n'
), ),
const FakeCommand( const FakeCommand(
command: <String>['adb', '-s', '1234', 'install', '-t', '-r', '--user', '10', 'app.apk'], command: <String>['adb', '-s', '1234', 'install', '-t', '-r', '--user', '10', 'app-debug.apk'],
exitCode: 1, exitCode: 1,
stderr: '[INSTALL_FAILED_INSUFFICIENT_STORAGE]', stderr: '[INSTALL_FAILED_INSUFFICIENT_STORAGE]',
), ),
]); ]);
final File apk = fileSystem.file('app.apk')..createSync(); final File apk = fileSystem.file('app-debug.apk')..createSync();
final AndroidApk androidApk = AndroidApk( final AndroidApk androidApk = AndroidApk(
applicationPackage: apk, applicationPackage: apk,
id: 'app', id: 'app',
......
...@@ -121,6 +121,20 @@ void main() { ...@@ -121,6 +121,20 @@ void main() {
}); });
group('listApkPaths', () { group('listApkPaths', () {
testWithoutContext('Finds APK without flavor in debug', () {
final Iterable<String> apks = listApkPaths(
const AndroidBuildInfo(BuildInfo(BuildMode.debug, '', treeShakeIcons: false)),
);
expect(apks, <String>['app-debug.apk']);
});
testWithoutContext('Finds APK with flavor in debug', () {
final Iterable<String> apks = listApkPaths(
const AndroidBuildInfo(BuildInfo(BuildMode.debug, 'flavor1', treeShakeIcons: false)),
);
expect(apks, <String>['app-flavor1-debug.apk']);
});
testWithoutContext('Finds APK without flavor in release', () { testWithoutContext('Finds APK without flavor in release', () {
final Iterable<String> apks = listApkPaths( final Iterable<String> apks = listApkPaths(
const AndroidBuildInfo(BuildInfo(BuildMode.release, '', treeShakeIcons: false)), const AndroidBuildInfo(BuildInfo(BuildMode.release, '', treeShakeIcons: false)),
......
...@@ -57,7 +57,7 @@ void main() { ...@@ -57,7 +57,7 @@ void main() {
testUsingContext('Licenses not available, platform and buildtools available, apk exists', () async { testUsingContext('Licenses not available, platform and buildtools available, apk exists', () async {
const String aaptPath = 'aaptPath'; const String aaptPath = 'aaptPath';
final File apkFile = globals.fs.file('app.apk'); final File apkFile = globals.fs.file('app-debug.apk');
final FakeAndroidSdkVersion sdkVersion = FakeAndroidSdkVersion(); final FakeAndroidSdkVersion sdkVersion = FakeAndroidSdkVersion();
sdkVersion.aaptPath = aaptPath; sdkVersion.aaptPath = aaptPath;
sdk.latestVersion = sdkVersion; sdk.latestVersion = sdkVersion;
...@@ -81,7 +81,7 @@ void main() { ...@@ -81,7 +81,7 @@ void main() {
TargetPlatform.android_arm, TargetPlatform.android_arm,
applicationBinary: apkFile, applicationBinary: apkFile,
))!; ))!;
expect(applicationPackage.name, 'app.apk'); expect(applicationPackage.name, 'app-debug.apk');
expect(applicationPackage, isA<PrebuiltApplicationPackage>()); expect(applicationPackage, isA<PrebuiltApplicationPackage>());
expect((applicationPackage as PrebuiltApplicationPackage).applicationPackage.path, apkFile.path); expect((applicationPackage as PrebuiltApplicationPackage).applicationPackage.path, apkFile.path);
expect(fakeProcessManager, hasNoRemainingExpectations); expect(fakeProcessManager, hasNoRemainingExpectations);
...@@ -103,7 +103,7 @@ void main() { ...@@ -103,7 +103,7 @@ void main() {
await ApplicationPackageFactory.instance!.getPackageForPlatform( await ApplicationPackageFactory.instance!.getPackageForPlatform(
TargetPlatform.android_arm, TargetPlatform.android_arm,
applicationBinary: globals.fs.file('app.apk'), applicationBinary: globals.fs.file('app-debug.apk'),
); );
expect(fakeProcessManager, hasNoRemainingExpectations); expect(fakeProcessManager, hasNoRemainingExpectations);
}, overrides: overrides); }, overrides: overrides);
......
...@@ -312,7 +312,7 @@ void main() { ...@@ -312,7 +312,7 @@ void main() {
<FlutterDevice>[ <FlutterDevice>[
flutterDevice, flutterDevice,
], ],
applicationBinary: globals.fs.file('app.apk'), applicationBinary: globals.fs.file('app-debug.apk'),
stayResident: false, stayResident: false,
debuggingOptions: DebuggingOptions.enabled(BuildInfo.debug), debuggingOptions: DebuggingOptions.enabled(BuildInfo.debug),
target: 'main.dart', target: 'main.dart',
......
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