Enable R8 (#40453)
diff --git a/packages/flutter_tools/gradle/flutter.gradle b/packages/flutter_tools/gradle/flutter.gradle
index 7d26259..e11d7ff 100644
--- a/packages/flutter_tools/gradle/flutter.gradle
+++ b/packages/flutter_tools/gradle/flutter.gradle
@@ -159,8 +159,12 @@
"gradle", "flutter_proguard_rules.pro")
project.android.buildTypes {
release {
+ // Enables code shrinking, obfuscation, and optimization for only
+ // your project's release build type.
minifyEnabled true
- useProguard true
+ // Enables resource shrinking, which is performed by the
+ // Android Gradle plugin.
+ shrinkResources true
// Fallback to `android/app/proguard-rules.pro`.
// This way, custom Proguard rules can be configured as needed.
proguardFiles project.android.getDefaultProguardFile("proguard-android.txt"), flutterProguardRules, "proguard-rules.pro"
diff --git a/packages/flutter_tools/lib/src/android/gradle.dart b/packages/flutter_tools/lib/src/android/gradle.dart
index 049065a..c670388 100644
--- a/packages/flutter_tools/lib/src/android/gradle.dart
+++ b/packages/flutter_tools/lib/src/android/gradle.dart
@@ -306,6 +306,10 @@
final Status status = logger.startProgress('Initializing gradle...',
timeout: timeoutConfiguration.slowOperation);
+
+ // Update the project if needed.
+ // TODO(egarciad): https://github.com/flutter/flutter/issues/40460.
+ migrateToR8(android);
injectGradleWrapperIfNeeded(android);
final String gradle = _locateGradlewExecutable(android);
@@ -335,6 +339,31 @@
return gradle;
}
+/// Migrates the Android's [directory] to R8.
+/// https://developer.android.com/studio/build/shrink-code
+@visibleForTesting
+void migrateToR8(Directory directory) {
+ final File gradleProperties = directory.childFile('gradle.properties');
+ if (!gradleProperties.existsSync()) {
+ throwToolExit('Expected file ${gradleProperties.path}.');
+ }
+ final String propertiesContent = gradleProperties.readAsStringSync();
+ if (propertiesContent.contains('android.enableR8')) {
+ printTrace('gradle.properties already sets `android.enableR8`');
+ return;
+ }
+ printTrace('set `android.enableR8=true` in gradle.properties');
+ try {
+ gradleProperties
+ .writeAsStringSync('android.enableR8=true\n', mode: FileMode.append);
+ } on FileSystemException {
+ throwToolExit(
+ 'The tool failed to add `android.enableR8=true` to ${gradleProperties.path}. '
+ 'Please update the file manually and try this command again.'
+ );
+ }
+}
+
/// Injects the Gradle wrapper files if any of these files don't exist in [directory].
void injectGradleWrapperIfNeeded(Directory directory) {
copyDirectorySync(
@@ -754,8 +783,8 @@
if (androidBuildInfo.splitPerAbi) {
command.add('-Psplit-per-abi=true');
}
- if (androidBuildInfo.proguard) {
- command.add('-Pproguard=true');
+ if (androidBuildInfo.shrink) {
+ command.add('-Pshrink=true');
}
if (androidBuildInfo.targetArchs.isNotEmpty) {
final String targetPlatforms = androidBuildInfo.targetArchs
@@ -772,7 +801,7 @@
}
command.add(assembleTask);
bool potentialAndroidXFailure = false;
- bool potentialProguardFailure = false;
+ bool potentialR8Failure = false;
final Stopwatch sw = Stopwatch()..start();
int exitCode = 1;
try {
@@ -789,10 +818,10 @@
if (!isAndroidXPluginWarning && androidXFailureRegex.hasMatch(line)) {
potentialAndroidXFailure = true;
}
- // Proguard errors include this url.
- if (!potentialProguardFailure && androidBuildInfo.proguard &&
- line.contains('http://proguard.sourceforge.net')) {
- potentialProguardFailure = true;
+ // R8 errors include references to this package.
+ if (!potentialR8Failure && androidBuildInfo.shrink &&
+ line.contains('com.android.tools.r8')) {
+ potentialR8Failure = true;
}
// Always print the full line in verbose mode.
if (logger.isVerbose) {
@@ -808,12 +837,12 @@
}
if (exitCode != 0) {
- if (potentialProguardFailure) {
+ if (potentialR8Failure) {
final String exclamationMark = terminal.color('[!]', TerminalColor.red);
- printStatus('$exclamationMark Proguard may have failed to optimize the Java bytecode.', emphasis: true);
- printStatus('To disable proguard, pass the `--no-proguard` flag to this command.', indent: 4);
- printStatus('To learn more about Proguard, see: https://flutter.dev/docs/deployment/android#enabling-proguard', indent: 4);
- BuildEvent('proguard-failure').send();
+ printStatus('$exclamationMark The shrinker may have failed to optimize the Java bytecode.', emphasis: true);
+ printStatus('To disable the shrinker, pass the `--no-shrink` flag to this command.', indent: 4);
+ printStatus('To learn more, see: https://developer.android.com/studio/build/shrink-code', indent: 4);
+ BuildEvent('r8-failure').send();
} else if (potentialAndroidXFailure) {
printStatus('AndroidX incompatibilities may have caused this build to fail. See https://goo.gl/CP92wY.');
BuildEvent('android-x-failure').send();
diff --git a/packages/flutter_tools/lib/src/build_info.dart b/packages/flutter_tools/lib/src/build_info.dart
index c406438..57ee601 100644
--- a/packages/flutter_tools/lib/src/build_info.dart
+++ b/packages/flutter_tools/lib/src/build_info.dart
@@ -92,7 +92,7 @@
AndroidArch.arm64_v8a,
],
this.splitPerAbi = false,
- this.proguard = false,
+ this.shrink = false,
});
// The build info containing the mode and flavor.
@@ -105,8 +105,8 @@
/// will be produced.
final bool splitPerAbi;
- /// Whether to enable Proguard on release mode.
- final bool proguard;
+ /// Whether to enable code shrinking on release mode.
+ final bool shrink;
/// The target platforms for the build.
final Iterable<AndroidArch> targetArchs;
diff --git a/packages/flutter_tools/lib/src/commands/build_apk.dart b/packages/flutter_tools/lib/src/commands/build_apk.dart
index a27d9f4..8936f0f 100644
--- a/packages/flutter_tools/lib/src/commands/build_apk.dart
+++ b/packages/flutter_tools/lib/src/commands/build_apk.dart
@@ -21,6 +21,7 @@
usesPubOption();
usesBuildNumberOption();
usesBuildNameOption();
+ addShrinkingFlag();
argParser
..addFlag('split-per-abi',
@@ -28,12 +29,6 @@
help: 'Whether to split the APKs per ABIs. '
'To learn more, see: https://developer.android.com/studio/build/configure-apk-splits#configure-abi-split',
)
- ..addFlag('proguard',
- negatable: true,
- defaultsTo: false,
- help: 'Whether to enable Proguard on release mode. '
- 'To learn more, see: https://flutter.dev/docs/deployment/android#enabling-proguard',
- )
..addMultiOption('target-platform',
splitCommas: true,
defaultsTo: <String>['android-arm', 'android-arm64'],
@@ -83,10 +78,11 @@
@override
Future<FlutterCommandResult> runCommand() async {
final BuildInfo buildInfo = getBuildInfo();
- final AndroidBuildInfo androidBuildInfo = AndroidBuildInfo(buildInfo,
+ final AndroidBuildInfo androidBuildInfo = AndroidBuildInfo(
+ buildInfo,
splitPerAbi: argResults['split-per-abi'],
targetArchs: argResults['target-platform'].map<AndroidArch>(getAndroidArchForName),
- proguard: argResults['proguard'],
+ shrink: argResults['shrink'],
);
if (buildInfo.isRelease && !androidBuildInfo.splitPerAbi && androidBuildInfo.targetArchs.length > 1) {
diff --git a/packages/flutter_tools/lib/src/commands/build_appbundle.dart b/packages/flutter_tools/lib/src/commands/build_appbundle.dart
index 1a53b52..bfea24f 100644
--- a/packages/flutter_tools/lib/src/commands/build_appbundle.dart
+++ b/packages/flutter_tools/lib/src/commands/build_appbundle.dart
@@ -19,15 +19,10 @@
usesPubOption();
usesBuildNumberOption();
usesBuildNameOption();
+ addShrinkingFlag();
argParser
..addFlag('track-widget-creation', negatable: false, hide: !verboseHelp)
- ..addFlag('proguard',
- negatable: true,
- defaultsTo: false,
- help: 'Whether to enable Proguard on release mode. '
- 'To learn more, see: https://flutter.dev/docs/deployment/android#enabling-proguard',
- )
..addMultiOption('target-platform',
splitCommas: true,
defaultsTo: <String>['android-arm', 'android-arm64'],
@@ -70,7 +65,7 @@
Future<FlutterCommandResult> runCommand() async {
final AndroidBuildInfo androidBuildInfo = AndroidBuildInfo(getBuildInfo(),
targetArchs: argResults['target-platform'].map<AndroidArch>(getAndroidArchForName),
- proguard: argResults['proguard'],
+ shrink: argResults['shrink'],
);
await androidBuilder.buildAab(
project: FlutterProject.current(),
diff --git a/packages/flutter_tools/lib/src/runner/flutter_command.dart b/packages/flutter_tools/lib/src/runner/flutter_command.dart
index e22c692..597143e 100644
--- a/packages/flutter_tools/lib/src/runner/flutter_command.dart
+++ b/packages/flutter_tools/lib/src/runner/flutter_command.dart
@@ -277,6 +277,19 @@
help: 'Build a release version of your app${defaultToRelease ? ' (default mode)' : ''}.');
}
+ void addShrinkingFlag() {
+ argParser.addFlag('shrink',
+ negatable: true,
+ defaultsTo: true,
+ help: 'Whether to enable code shrinking on release mode.'
+ 'When enabling shrinking, you also benefit from obfuscation, '
+ 'which shortens the names of your app’s classes and members, '
+ 'and optimization, which applies more aggressive strategies to '
+ 'further reduce the size of your app.'
+ 'To learn more, see: https://developer.android.com/studio/build/shrink-code'
+ );
+ }
+
void usesFuchsiaOptions({ bool hide = false }) {
argParser.addOption(
'target-model',
diff --git a/packages/flutter_tools/templates/app/android.tmpl/gradle.properties.tmpl b/packages/flutter_tools/templates/app/android.tmpl/gradle.properties.tmpl
index a2296f5..2a0d268 100644
--- a/packages/flutter_tools/templates/app/android.tmpl/gradle.properties.tmpl
+++ b/packages/flutter_tools/templates/app/android.tmpl/gradle.properties.tmpl
@@ -1,5 +1,5 @@
org.gradle.jvmargs=-Xmx1536M
-
+android.enableR8=true
{{#androidX}}
android.useAndroidX=true
android.enableJetifier=true
diff --git a/packages/flutter_tools/templates/module/android/gradle/gradle.properties.tmpl b/packages/flutter_tools/templates/module/android/gradle/gradle.properties.tmpl
index a2296f5..2a0d268 100644
--- a/packages/flutter_tools/templates/module/android/gradle/gradle.properties.tmpl
+++ b/packages/flutter_tools/templates/module/android/gradle/gradle.properties.tmpl
@@ -1,5 +1,5 @@
org.gradle.jvmargs=-Xmx1536M
-
+android.enableR8=true
{{#androidX}}
android.useAndroidX=true
android.enableJetifier=true
diff --git a/packages/flutter_tools/templates/plugin/android.tmpl/gradle.properties.tmpl b/packages/flutter_tools/templates/plugin/android.tmpl/gradle.properties.tmpl
index a2296f5..2a0d268 100644
--- a/packages/flutter_tools/templates/plugin/android.tmpl/gradle.properties.tmpl
+++ b/packages/flutter_tools/templates/plugin/android.tmpl/gradle.properties.tmpl
@@ -1,5 +1,5 @@
org.gradle.jvmargs=-Xmx1536M
-
+android.enableR8=true
{{#androidX}}
android.useAndroidX=true
android.enableJetifier=true
diff --git a/packages/flutter_tools/test/general.shard/android/gradle_test.dart b/packages/flutter_tools/test/general.shard/android/gradle_test.dart
index e583a46..b650ab0 100644
--- a/packages/flutter_tools/test/general.shard/android/gradle_test.dart
+++ b/packages/flutter_tools/test/general.shard/android/gradle_test.dart
@@ -3,7 +3,6 @@
// found in the LICENSE file.
import 'dart:async';
-import 'dart:io';
import 'package:file/memory.dart';
import 'package:flutter_tools/src/android/android_sdk.dart';
@@ -13,6 +12,7 @@
import 'package:flutter_tools/src/artifacts.dart';
import 'package:flutter_tools/src/base/common.dart';
import 'package:flutter_tools/src/base/file_system.dart';
+import 'package:flutter_tools/src/base/io.dart';
import 'package:flutter_tools/src/base/os.dart';
import 'package:flutter_tools/src/base/platform.dart';
import 'package:flutter_tools/src/build_info.dart';
@@ -867,6 +867,13 @@
gradleWrapperDirectory
.childFile(gradleBinary)
.writeAsStringSync('irrelevant');
+ fs.currentDirectory
+ .childDirectory('android')
+ .createSync();
+ fs.currentDirectory
+ .childDirectory('android')
+ .childFile('gradle.properties')
+ .writeAsStringSync('irrelevant');
gradleWrapperDirectory
.childDirectory('gradle')
.childDirectory('wrapper')
@@ -1072,6 +1079,82 @@
});
});
+ group('migrateToR8', () {
+ MemoryFileSystem memoryFileSystem;
+
+ setUp(() {
+ memoryFileSystem = MemoryFileSystem();
+ });
+
+ testUsingContext('throws ToolExit if gradle.properties doesn\'t exist', () {
+ final Directory sampleAppAndroid = fs.directory('/sample-app/android');
+ sampleAppAndroid.createSync(recursive: true);
+
+ expect(() {
+ migrateToR8(sampleAppAndroid);
+ }, throwsToolExit(message: 'Expected file ${sampleAppAndroid.path}'));
+
+ }, overrides: <Type, Generator>{
+ FileSystem: () => memoryFileSystem,
+ });
+
+ testUsingContext('throws ToolExit if it cannot write gradle.properties', () {
+ final MockDirectory sampleAppAndroid = MockDirectory();
+ final MockFile gradleProperties = MockFile();
+
+ when(gradleProperties.path).thenReturn('foo/gradle.properties');
+ when(gradleProperties.existsSync()).thenReturn(true);
+ when(gradleProperties.readAsStringSync()).thenReturn('');
+ when(gradleProperties.writeAsStringSync('android.enableR8=true\n', mode: FileMode.append))
+ .thenThrow(const FileSystemException());
+
+ when(sampleAppAndroid.childFile('gradle.properties'))
+ .thenReturn(gradleProperties);
+
+ expect(() {
+ migrateToR8(sampleAppAndroid);
+ },
+ throwsToolExit(message:
+ 'The tool failed to add `android.enableR8=true` to foo/gradle.properties. '
+ 'Please update the file manually and try this command again.'));
+ });
+
+ testUsingContext('does not update gradle.properties if it already uses R8', () {
+ final Directory sampleAppAndroid = fs.directory('/sample-app/android');
+ sampleAppAndroid.createSync(recursive: true);
+ sampleAppAndroid.childFile('gradle.properties')
+ .writeAsStringSync('android.enableR8=true');
+
+ migrateToR8(sampleAppAndroid);
+
+ expect(testLogger.traceText,
+ contains('gradle.properties already sets `android.enableR8`'));
+ expect(sampleAppAndroid.childFile('gradle.properties').readAsStringSync(),
+ equals('android.enableR8=true'));
+ }, overrides: <Type, Generator>{
+ FileSystem: () => memoryFileSystem,
+ });
+
+ testUsingContext('sets android.enableR8=true', () {
+ final Directory sampleAppAndroid = fs.directory('/sample-app/android');
+ sampleAppAndroid.createSync(recursive: true);
+ sampleAppAndroid.childFile('gradle.properties')
+ .writeAsStringSync('org.gradle.jvmargs=-Xmx1536M\n');
+
+ migrateToR8(sampleAppAndroid);
+
+ expect(testLogger.traceText, contains('set `android.enableR8=true` in gradle.properties'));
+ expect(sampleAppAndroid.childFile('gradle.properties').readAsStringSync(),
+ equals(
+ 'org.gradle.jvmargs=-Xmx1536M\n'
+ 'android.enableR8=true\n'
+ )
+ );
+ }, overrides: <Type, Generator>{
+ FileSystem: () => memoryFileSystem,
+ });
+ });
+
group('gradle build', () {
MockAndroidSdk mockAndroidSdk;
MockAndroidStudio mockAndroidStudio;
@@ -1136,6 +1219,9 @@
final File gradlew = fs.file('path/to/project/.android/gradlew');
gradlew.createSync(recursive: true);
+ fs.file('path/to/project/.android/gradle.properties')
+ .writeAsStringSync('irrelevant');
+
when(mockProcessManager.run(
<String> ['/path/to/project/.android/gradlew', '-v'],
workingDirectory: anyNamed('workingDirectory'),
@@ -1198,9 +1284,11 @@
return FakePlatform.fromPlatform(const LocalPlatform())..operatingSystem = name;
}
+class MockAndroidStudio extends Mock implements AndroidStudio {}
+class MockDirectory extends Mock implements Directory {}
+class MockFile extends Mock implements File {}
+class MockGradleProject extends Mock implements GradleProject {}
class MockLocalEngineArtifacts extends Mock implements LocalEngineArtifacts {}
class MockProcessManager extends Mock implements ProcessManager {}
class MockXcodeProjectInterpreter extends Mock implements XcodeProjectInterpreter {}
-class MockGradleProject extends Mock implements GradleProject {}
class MockitoAndroidSdk extends Mock implements AndroidSdk {}
-class MockAndroidStudio extends Mock implements AndroidStudio {}
diff --git a/packages/flutter_tools/test/general.shard/application_package_test.dart b/packages/flutter_tools/test/general.shard/application_package_test.dart
index a374142..05855b0 100644
--- a/packages/flutter_tools/test/general.shard/application_package_test.dart
+++ b/packages/flutter_tools/test/general.shard/application_package_test.dart
@@ -103,6 +103,10 @@
platform.isWindows ? 'gradlew.bat' : 'gradlew',
)..createSync(recursive: true);
+ project.android.hostAppGradleRoot
+ .childFile('gradle.properties')
+ .writeAsStringSync('irrelevant');
+
final Directory gradleWrapperDir = fs.systemTempDirectory.createTempSync('gradle_wrapper.');
when(mockCache.getArtifactDirectory('gradle_wrapper')).thenReturn(gradleWrapperDir);
diff --git a/packages/flutter_tools/test/general.shard/commands/build_apk_test.dart b/packages/flutter_tools/test/general.shard/commands/build_apk_test.dart
index f3d19b8..1c961ad 100644
--- a/packages/flutter_tools/test/general.shard/commands/build_apk_test.dart
+++ b/packages/flutter_tools/test/general.shard/commands/build_apk_test.dart
@@ -137,7 +137,7 @@
tryToDelete(tempDir);
});
- testUsingContext('proguard is enabled by default on release mode', () async {
+ testUsingContext('shrinking is enabled by default on release mode', () async {
final String projectPath = await createProject(tempDir,
arguments: <String>['--no-pub', '--template=app']);
@@ -151,7 +151,7 @@
'-q',
'-Ptarget=${fs.path.join(tempDir.path, 'flutter_project', 'lib', 'main.dart')}',
'-Ptrack-widget-creation=false',
- '-Pproguard=true',
+ '-Pshrink=true',
'-Ptarget-platform=android-arm,android-arm64',
'assembleRelease',
],
@@ -165,17 +165,16 @@
GradleUtils: () => GradleUtils(),
ProcessManager: () => mockProcessManager,
},
- skip: true,
timeout: allowForCreateFlutterProject);
- testUsingContext('proguard is disabled when --no-proguard is passed', () async {
+ testUsingContext('shrinking is disabled when --no-shrink is passed', () async {
final String projectPath = await createProject(tempDir,
arguments: <String>['--no-pub', '--template=app']);
await expectLater(() async {
await runBuildApkCommand(
projectPath,
- arguments: <String>['--no-proguard'],
+ arguments: <String>['--no-shrink'],
);
}, throwsToolExit(message: 'Gradle task assembleRelease failed with exit code 1'));
@@ -198,10 +197,9 @@
GradleUtils: () => GradleUtils(),
ProcessManager: () => mockProcessManager,
},
- skip: true,
timeout: allowForCreateFlutterProject);
- testUsingContext('guides the user when proguard fails', () async {
+ testUsingContext('guides the user when the shrinker fails', () async {
final String projectPath = await createProject(tempDir,
arguments: <String>['--no-pub', '--template=app']);
@@ -211,22 +209,20 @@
'-q',
'-Ptarget=${fs.path.join(tempDir.path, 'flutter_project', 'lib', 'main.dart')}',
'-Ptrack-widget-creation=false',
- '-Pproguard=true',
+ '-Pshrink=true',
'-Ptarget-platform=android-arm,android-arm64',
'assembleRelease',
],
workingDirectory: anyNamed('workingDirectory'),
environment: anyNamed('environment'),
)).thenAnswer((_) {
- const String proguardStdoutWarning =
- 'Warning: there were 6 unresolved references to program class members.'
- 'Your input classes appear to be inconsistent.'
- 'You may need to recompile the code.'
- '(http://proguard.sourceforge.net/manual/troubleshooting.html#unresolvedprogramclassmember)';
+ const String r8StdoutWarning =
+ 'Execution failed for task \':app:transformClassesAndResourcesWithR8ForStageInternal\'.'
+ '> com.android.tools.r8.CompilationFailedException: Compilation failed to complete';
return Future<Process>.value(
createMockProcess(
exitCode: 1,
- stdout: proguardStdoutWarning,
+ stdout: r8StdoutWarning,
)
);
});
@@ -238,15 +234,15 @@
}, throwsToolExit(message: 'Gradle task assembleRelease failed with exit code 1'));
expect(testLogger.statusText,
- contains('Proguard may have failed to optimize the Java bytecode.'));
+ contains('The shrinker may have failed to optimize the Java bytecode.'));
expect(testLogger.statusText,
- contains('To disable proguard, pass the `--no-proguard` flag to this command.'));
+ contains('To disable the shrinker, pass the `--no-shrink` flag to this command.'));
expect(testLogger.statusText,
- contains('To learn more about Proguard, see: https://flutter.dev/docs/deployment/android#enabling-proguard'));
+ contains('To learn more, see: https://developer.android.com/studio/build/shrink-code'));
verify(mockUsage.sendEvent(
'build-apk',
- 'proguard-failure',
+ 'r8-failure',
parameters: anyNamed('parameters'),
)).called(1);
},
@@ -257,7 +253,6 @@
ProcessManager: () => mockProcessManager,
Usage: () => mockUsage,
},
- skip: true,
timeout: allowForCreateFlutterProject);
});
}
diff --git a/packages/flutter_tools/test/general.shard/commands/build_appbundle_test.dart b/packages/flutter_tools/test/general.shard/commands/build_appbundle_test.dart
index 4548e3c..4a7d98f 100644
--- a/packages/flutter_tools/test/general.shard/commands/build_appbundle_test.dart
+++ b/packages/flutter_tools/test/general.shard/commands/build_appbundle_test.dart
@@ -75,7 +75,7 @@
}, timeout: allowForCreateFlutterProject);
});
- group('Flags', () {
+ group('Gradle', () {
Directory tempDir;
ProcessManager mockProcessManager;
MockAndroidSdk mockAndroidSdk;
@@ -122,7 +122,7 @@
tryToDelete(tempDir);
});
- testUsingContext('proguard is enabled by default on release mode', () async {
+ testUsingContext('shrinking is enabled by default on release mode', () async {
final String projectPath = await createProject(
tempDir,
arguments: <String>['--no-pub', '--template=app'],
@@ -138,7 +138,7 @@
'-q',
'-Ptarget=${fs.path.join(tempDir.path, 'flutter_project', 'lib', 'main.dart')}',
'-Ptrack-widget-creation=false',
- '-Pproguard=true',
+ '-Pshrink=true',
'-Ptarget-platform=android-arm,android-arm64',
'bundleRelease',
],
@@ -152,10 +152,9 @@
GradleUtils: () => GradleUtils(),
ProcessManager: () => mockProcessManager,
},
- skip: true,
timeout: allowForCreateFlutterProject);
- testUsingContext('proguard is disabled when --no-proguard is passed', () async {
+ testUsingContext('shrinking is disabled when --no-shrink is passed', () async {
final String projectPath = await createProject(
tempDir,
arguments: <String>['--no-pub', '--template=app'],
@@ -164,7 +163,7 @@
await expectLater(() async {
await runBuildAppBundleCommand(
projectPath,
- arguments: <String>['--no-proguard'],
+ arguments: <String>['--no-shrink'],
);
}, throwsToolExit(message: 'Gradle task bundleRelease failed with exit code 1'));
@@ -187,10 +186,9 @@
GradleUtils: () => GradleUtils(),
ProcessManager: () => mockProcessManager,
},
- skip: true,
timeout: allowForCreateFlutterProject);
- testUsingContext('guides the user when proguard fails', () async {
+ testUsingContext('guides the user when the shrinker fails', () async {
final String projectPath = await createProject(tempDir,
arguments: <String>['--no-pub', '--template=app']);
@@ -200,22 +198,20 @@
'-q',
'-Ptarget=${fs.path.join(tempDir.path, 'flutter_project', 'lib', 'main.dart')}',
'-Ptrack-widget-creation=false',
- '-Pproguard=true',
+ '-Pshrink=true',
'-Ptarget-platform=android-arm,android-arm64',
'bundleRelease',
],
workingDirectory: anyNamed('workingDirectory'),
environment: anyNamed('environment'),
)).thenAnswer((_) {
- const String proguardStdoutWarning =
- 'Warning: there were 6 unresolved references to program class members.'
- 'Your input classes appear to be inconsistent.'
- 'You may need to recompile the code.'
- '(http://proguard.sourceforge.net/manual/troubleshooting.html#unresolvedprogramclassmember)';
+ const String r8StdoutWarning =
+ 'Execution failed for task \':app:transformClassesAndResourcesWithR8ForStageInternal\'.'
+ '> com.android.tools.r8.CompilationFailedException: Compilation failed to complete';
return Future<Process>.value(
createMockProcess(
exitCode: 1,
- stdout: proguardStdoutWarning,
+ stdout: r8StdoutWarning,
)
);
});
@@ -227,15 +223,15 @@
}, throwsToolExit(message: 'Gradle task bundleRelease failed with exit code 1'));
expect(testLogger.statusText,
- contains('Proguard may have failed to optimize the Java bytecode.'));
+ contains('The shrinker may have failed to optimize the Java bytecode.'));
expect(testLogger.statusText,
- contains('To disable proguard, pass the `--no-proguard` flag to this command.'));
+ contains('To disable the shrinker, pass the `--no-shrink` flag to this command.'));
expect(testLogger.statusText,
- contains('To learn more about Proguard, see: https://flutter.dev/docs/deployment/android#enabling-proguard'));
+ contains('To learn more, see: https://developer.android.com/studio/build/shrink-code'));
verify(mockUsage.sendEvent(
'build-appbundle',
- 'proguard-failure',
+ 'r8-failure',
parameters: anyNamed('parameters'),
)).called(1);
},
@@ -246,7 +242,6 @@
ProcessManager: () => mockProcessManager,
Usage: () => mockUsage,
},
- skip: true,
timeout: allowForCreateFlutterProject);
});
}