Skip to content

Commit fd827e3

Browse files
authored
Expose versionCode and versionName from local.properties in FlutterExtension (#141417)
This PR has no issue. I got this cool idea and decided to quickly try it out, and it works. ### Summary This will allow Flutter Developers to have less code in their Android Gradle buildscripts. ```diff plugins { id "com.android.application" id "dev.flutter.flutter-gradle-plugin" id "kotlin-android" } -def localProperties = new Properties() -def localPropertiesFile = rootProject.file("local.properties") -if (localPropertiesFile.exists()) { - localPropertiesFile.withReader("UTF-8") { reader -> - localProperties.load(reader) - } -} - -def flutterVersionCode = localProperties.getProperty("flutter.versionCode") -if (flutterVersionCode == null) { - flutterVersionCode = "1" -} - -def flutterVersionName = localProperties.getProperty("flutter.versionName") -if (flutterVersionName == null) { - flutterVersionName = "1.0" -} - -def keystorePropertiesFile = rootProject.file("keystore.properties") -def keystoreProperties = new Properties() - keystoreProperties.load(new FileInputStream(keystorePropertiesFile)) android { applicationId "pl.baftek.discoverrudy" minSdk 21 targetSdk 34 - versionCode flutterVersionCode.toInteger() - versionName flutterVersionName + versionCode flutter.versionCode() + versionName flutter.versionName() } ``` The boilerplate that loads 'local.properties' can live in Flutter Gradle Plugin. ### Concerns I was worried about lifecycle/ordering issues, so I tested it. To Flutter Gradle Plugin, I added: ```diff class FlutterPlugin implements Plugin<Project> { //... @OverRide void apply(Project project) { + project.logger.quiet("Start applying FGP") // ... } } ``` and to my `android/app/build.gradle` I added: ```diff android { + logger.quiet("Start evaluating android block") namespace "pl.bartekpacia.awesomeapp" compileSdk 34 defaultConfig { applicationId "pl.baftek.discoverrudy" minSdk 21 targetSdk 34 versionCode flutter.versionCode() versionName flutter.versionName() } ``` Gradle first applies the plugins (which sets versionCode and versionName on FlutterExtension), and then it executes the `android {}` extension block: ``` $ ./gradlew :app:assembleDebug > Configure project :app Start applying FGP Start evaluating android block BUILD SUCCESSFUL in 2s 383 actionable tasks: 10 executed, 373 up-to-date ``` So ordering is fine.
1 parent d35ee11 commit fd827e3

File tree

3 files changed

+54
-33
lines changed

3 files changed

+54
-33
lines changed

examples/hello_world/android/app/build.gradle

Lines changed: 2 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -7,24 +7,6 @@ plugins {
77
id "dev.flutter.flutter-gradle-plugin"
88
}
99

10-
def localProperties = new Properties()
11-
def localPropertiesFile = rootProject.file('local.properties')
12-
if (localPropertiesFile.exists()) {
13-
localPropertiesFile.withReader('UTF-8') { reader ->
14-
localProperties.load(reader)
15-
}
16-
}
17-
18-
def flutterVersionCode = localProperties.getProperty('flutter.versionCode')
19-
if (flutterVersionCode == null) {
20-
flutterVersionCode = '1'
21-
}
22-
23-
def flutterVersionName = localProperties.getProperty('flutter.versionName')
24-
if (flutterVersionName == null) {
25-
flutterVersionName = '1.0'
26-
}
27-
2810
android {
2911
namespace "io.flutter.examples.hello_world"
3012
compileSdk flutter.compileSdkVersion
@@ -38,8 +20,8 @@ android {
3820
applicationId "io.flutter.examples.hello_world"
3921
minSdkVersion flutter.minSdkVersion
4022
targetSdkVersion flutter.targetSdkVersion
41-
versionCode flutterVersionCode.toInteger()
42-
versionName flutterVersionName
23+
versionCode flutter.versionCode()
24+
versionName flutter.versionName()
4325
}
4426

4527
buildTypes {

examples/layers/android/app/build.gradle

Lines changed: 2 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -15,16 +15,6 @@ if (flutterRoot == null) {
1515
throw new GradleException("Flutter SDK not found. Define location with flutter.sdk in the local.properties file.")
1616
}
1717

18-
def flutterVersionCode = localProperties.getProperty('flutter.versionCode')
19-
if (flutterVersionCode == null) {
20-
flutterVersionCode = '1'
21-
}
22-
23-
def flutterVersionName = localProperties.getProperty('flutter.versionName')
24-
if (flutterVersionName == null) {
25-
flutterVersionName = '1.0'
26-
}
27-
2818
apply plugin: 'com.android.application'
2919
apply from: "$flutterRoot/packages/flutter_tools/gradle/flutter.gradle"
3020

@@ -41,8 +31,8 @@ android {
4131
applicationId "io.flutter.examples.layers"
4232
minSdkVersion flutter.minSdkVersion
4333
targetSdkVersion flutter.targetSdkVersion
44-
versionCode flutterVersionCode.toInteger()
45-
versionName flutterVersionName
34+
versionCode flutter.versionCode()
35+
versionName flutter.versionName()
4636
}
4737

4838
buildTypes {

packages/flutter_tools/gradle/src/main/groovy/flutter.groovy

Lines changed: 50 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,34 @@ class FlutterExtension {
6969

7070
/** Allows to override the target file. Otherwise, the target is lib/main.dart. */
7171
String target
72+
73+
/** The versionCode that was read from app's local.properties. */
74+
String flutterVersionCode = null
75+
76+
/** The versionName that was read from app's local.properties. */
77+
String flutterVersionName = null
78+
79+
/** Returns flutterVersionCode as an integer with error handling. */
80+
Integer versionCode() {
81+
if (flutterVersionCode == null) {
82+
throw new GradleException("flutterVersionCode must not be null.")
83+
}
84+
85+
if (!flutterVersionCode.isNumber()) {
86+
throw new GradleException("flutterVersionCode must be an integer.")
87+
}
88+
89+
return flutterVersionCode.toInteger()
90+
}
91+
92+
/** Returns flutterVersionName with error handling. */
93+
String versionName() {
94+
if (flutterVersionName == null) {
95+
throw new GradleException("flutterVersionName must not be null.")
96+
}
97+
98+
return flutterVersionName
99+
}
72100
}
73101

74102
// This buildscript block supplies dependencies for this file's own import
@@ -226,7 +254,28 @@ class FlutterPlugin implements Plugin<Project> {
226254
// Load shared gradle functions
227255
project.apply from: Paths.get(flutterRoot.absolutePath, "packages", "flutter_tools", "gradle", "src", "main", "groovy", "native_plugin_loader.groovy")
228256

229-
project.extensions.create("flutter", FlutterExtension)
257+
def extension = project.extensions.create("flutter", FlutterExtension)
258+
def localProperties = new Properties()
259+
def localPropertiesFile = rootProject.file("local.properties")
260+
if (localPropertiesFile.exists()) {
261+
localPropertiesFile.withReader("UTF-8") { reader ->
262+
localProperties.load(reader)
263+
}
264+
}
265+
266+
def flutterVersionCode = localProperties.getProperty("flutter.versionCode")
267+
if (flutterVersionCode == null) {
268+
flutterVersionCode = "1"
269+
}
270+
extension.flutterVersionCode = flutterVersionCode
271+
272+
273+
def flutterVersionName = localProperties.getProperty("flutter.versionName")
274+
if (flutterVersionName == null) {
275+
flutterVersionName = "1.0"
276+
}
277+
extension.flutterVersionName = flutterVersionName
278+
230279
this.addFlutterTasks(project)
231280

232281
// By default, assembling APKs generates fat APKs if multiple platforms are passed.

0 commit comments

Comments
 (0)