Skip to content

Commit b0a2299

Browse files
christopherfujinoEmmanuel Garcia
andauthored
Ensure apps can build while using AGP 3.3.0 (flutter#71964) (flutter#72754)
Co-authored-by: Emmanuel Garcia <egarciad@google.com>
1 parent 8f89f65 commit b0a2299

File tree

2 files changed

+108
-12
lines changed

2 files changed

+108
-12
lines changed

dev/devicelab/bin/tasks/android_plugin_example_app_build_test.dart

Lines changed: 79 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,6 @@ final String gradlewExecutable = Platform.isWindows ? '.\\$gradlew' : './$gradle
1515
/// Tests that a plugin example app can be built using the current Flutter Gradle plugin.
1616
Future<void> main() async {
1717
await task(() async {
18-
1918
section('Find Java');
2019

2120
final String javaHome = await findJavaHome();
@@ -32,22 +31,47 @@ Future<void> main() async {
3231
options: <String>['--android', '--no-ios'],
3332
);
3433

35-
final Directory tempDir = Directory.systemTemp.createTempSync('flutter_plugin_test.');
36-
final Directory projectDir = Directory(path.join(tempDir.path, 'plugin_test'));
34+
final Directory tempDir =
35+
Directory.systemTemp.createTempSync('flutter_plugin_test.');
36+
final Directory projectDir =
37+
Directory(path.join(tempDir.path, 'plugin_test'));
3738
try {
3839
await inDirectory(tempDir, () async {
3940
await flutter(
4041
'create',
41-
options: <String>['--template=plugin', '--platforms=android', 'plugin_test'],
42+
options: <String>[
43+
'--template=plugin',
44+
'--platforms=android',
45+
'plugin_test',
46+
],
4247
);
4348
});
4449

45-
final Directory exampleAppDir = Directory(path.join(projectDir.path, 'example'));
50+
final Directory exampleAppDir =
51+
Directory(path.join(projectDir.path, 'example'));
4652
if (!exists(exampleAppDir)) {
4753
return TaskResult.failure('Example app directory doesn\'t exist');
4854
}
4955

50-
section('Run flutter build apk');
56+
final File buildGradleFile =
57+
File(path.join(exampleAppDir.path, 'android', 'build.gradle'));
58+
59+
if (!exists(buildGradleFile)) {
60+
return TaskResult.failure('$buildGradleFile doesn\'t exist');
61+
}
62+
63+
final String buildGradle = buildGradleFile.readAsStringSync();
64+
final RegExp androidPluginRegExp =
65+
RegExp(r'com\.android\.tools\.build:gradle:(\d+\.\d+\.\d+)');
66+
67+
section('Use AGP 4.1.0');
68+
69+
String newBuildGradle = buildGradle.replaceAll(
70+
androidPluginRegExp, 'com.android.tools.build:gradle:4.1.0');
71+
print(newBuildGradle);
72+
buildGradleFile.writeAsString(newBuildGradle);
73+
74+
section('Run flutter build apk using AGP 4.1.0');
5175

5276
await inDirectory(exampleAppDir, () async {
5377
await flutter(
@@ -72,6 +96,55 @@ Future<void> main() async {
7296
return TaskResult.failure('Failed to build app-release.apk');
7397
}
7498

99+
section('Clean');
100+
101+
await inDirectory(exampleAppDir, () async {
102+
await flutter('clean');
103+
});
104+
105+
section('Remove Gradle wrapper');
106+
107+
Directory(path.join(exampleAppDir.path, 'android', 'gradle', 'wrapper'))
108+
.deleteSync(recursive: true);
109+
110+
section('Use AGP 3.3.0');
111+
112+
newBuildGradle = buildGradle.replaceAll(
113+
androidPluginRegExp, 'com.android.tools.build:gradle:3.3.0');
114+
print(newBuildGradle);
115+
buildGradleFile.writeAsString(newBuildGradle);
116+
117+
section('Enable R8 in gradle.properties');
118+
119+
final File gradleProperties =
120+
File(path.join(exampleAppDir.path, 'android', 'gradle.properties'));
121+
122+
if (!exists(gradleProperties)) {
123+
return TaskResult.failure('$gradleProperties doesn\'t exist');
124+
}
125+
126+
gradleProperties.writeAsString('''
127+
org.gradle.jvmargs=-Xmx1536M
128+
android.useAndroidX=true
129+
android.enableJetifier=true
130+
android.enableR8=true''');
131+
132+
section('Run flutter build apk using AGP 3.3.0');
133+
134+
await inDirectory(exampleAppDir, () async {
135+
await flutter(
136+
'build',
137+
options: <String>[
138+
'apk',
139+
'--target-platform=android-arm',
140+
],
141+
);
142+
});
143+
144+
if (!exists(File(exampleApk))) {
145+
return TaskResult.failure('Failed to build app-release.apk');
146+
}
147+
75148
return TaskResult.success(null);
76149
} on TaskResult catch (taskResult) {
77150
return taskResult;

packages/flutter_tools/gradle/flutter.gradle

Lines changed: 29 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ import org.gradle.api.tasks.InputFiles
2020
import org.gradle.api.tasks.OutputDirectory
2121
import org.gradle.api.tasks.TaskAction
2222
import org.gradle.api.tasks.bundling.Jar
23+
import org.gradle.util.VersionNumber
2324

2425
buildscript {
2526
repositories {
@@ -304,7 +305,7 @@ class FlutterPlugin implements Plugin<Project> {
304305
project.dependencies {
305306
implementation pluginProject
306307
}
307-
Closure addEmbeddingCompileOnlyDependency = { buildType ->
308+
Closure addEmbeddingDependencyToPlugin = { buildType ->
308309
String flutterBuildMode = buildModeFor(buildType)
309310
// In AGP 3.5, the embedding must be added as an API implementation,
310311
// so java8 features are desugared against the runtime classpath.
@@ -317,17 +318,39 @@ class FlutterPlugin implements Plugin<Project> {
317318
pluginProject.android.buildTypes {
318319
"${buildType.name}" {}
319320
}
320-
pluginProject.dependencies.add(
321-
"${buildType.name}CompileOnly",
322-
"io.flutter:flutter_embedding_$flutterBuildMode:$engineVersion")
321+
// The embedding is a compileOnly dependency of a Flutter plugin,
322+
// however prior to Gradle 6.0.0, it must be an API dependency.
323+
//
324+
// Not doing so, causes transitive dependency resolution conflicts.
325+
// That is, the embedding dependencies resolved in the plugin are
326+
// different than the ones resolved in the app.
327+
if (isGradleVersionGraterOrEqualThan('6.0.0')) {
328+
addCompileOnlyDependency(
329+
pluginProject,
330+
buildType.name,
331+
"io.flutter:flutter_embedding_$flutterBuildMode:$engineVersion"
332+
)
333+
} else {
334+
addApiDependencies(
335+
pluginProject,
336+
buildType.name,
337+
"io.flutter:flutter_embedding_$flutterBuildMode:$engineVersion"
338+
)
339+
}
323340
}
324341
// Wait until the Android plugin loaded.
325342
pluginProject.afterEvaluate {
326-
project.android.buildTypes.each addEmbeddingCompileOnlyDependency
327-
project.android.buildTypes.whenObjectAdded addEmbeddingCompileOnlyDependency
343+
project.android.buildTypes.each addEmbeddingDependencyToPlugin
344+
project.android.buildTypes.whenObjectAdded addEmbeddingDependencyToPlugin
328345
}
329346
}
330347

348+
// Returns `true` if the current Gradle version is greater or equal to the given version.
349+
private isGradleVersionGraterOrEqualThan(String version) {
350+
return VersionNumber.parse(project.gradle.gradleVersion)
351+
.compareTo(VersionNumber.parse(version)) >= 0
352+
}
353+
331354
// Returns `true` if the given path contains an `android/build.gradle` file.
332355
//
333356
// TODO(egarciad): Fix https://github.com/flutter/flutter/issues/39657.

0 commit comments

Comments
 (0)