Unverified Commit fd827e3a authored by Bartek Pacia's avatar Bartek Pacia Committed by GitHub

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.
parent d35ee11e
...@@ -7,24 +7,6 @@ plugins { ...@@ -7,24 +7,6 @@ plugins {
id "dev.flutter.flutter-gradle-plugin" id "dev.flutter.flutter-gradle-plugin"
} }
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'
}
android { android {
namespace "io.flutter.examples.hello_world" namespace "io.flutter.examples.hello_world"
compileSdk flutter.compileSdkVersion compileSdk flutter.compileSdkVersion
...@@ -38,8 +20,8 @@ android { ...@@ -38,8 +20,8 @@ android {
applicationId "io.flutter.examples.hello_world" applicationId "io.flutter.examples.hello_world"
minSdkVersion flutter.minSdkVersion minSdkVersion flutter.minSdkVersion
targetSdkVersion flutter.targetSdkVersion targetSdkVersion flutter.targetSdkVersion
versionCode flutterVersionCode.toInteger() versionCode flutter.versionCode()
versionName flutterVersionName versionName flutter.versionName()
} }
buildTypes { buildTypes {
......
...@@ -15,16 +15,6 @@ if (flutterRoot == null) { ...@@ -15,16 +15,6 @@ if (flutterRoot == null) {
throw new GradleException("Flutter SDK not found. Define location with flutter.sdk in the local.properties file.") throw new GradleException("Flutter SDK not found. Define location with flutter.sdk in the local.properties file.")
} }
def flutterVersionCode = localProperties.getProperty('flutter.versionCode')
if (flutterVersionCode == null) {
flutterVersionCode = '1'
}
def flutterVersionName = localProperties.getProperty('flutter.versionName')
if (flutterVersionName == null) {
flutterVersionName = '1.0'
}
apply plugin: 'com.android.application' apply plugin: 'com.android.application'
apply from: "$flutterRoot/packages/flutter_tools/gradle/flutter.gradle" apply from: "$flutterRoot/packages/flutter_tools/gradle/flutter.gradle"
...@@ -41,8 +31,8 @@ android { ...@@ -41,8 +31,8 @@ android {
applicationId "io.flutter.examples.layers" applicationId "io.flutter.examples.layers"
minSdkVersion flutter.minSdkVersion minSdkVersion flutter.minSdkVersion
targetSdkVersion flutter.targetSdkVersion targetSdkVersion flutter.targetSdkVersion
versionCode flutterVersionCode.toInteger() versionCode flutter.versionCode()
versionName flutterVersionName versionName flutter.versionName()
} }
buildTypes { buildTypes {
......
...@@ -69,6 +69,34 @@ class FlutterExtension { ...@@ -69,6 +69,34 @@ class FlutterExtension {
/** Allows to override the target file. Otherwise, the target is lib/main.dart. */ /** Allows to override the target file. Otherwise, the target is lib/main.dart. */
String target String target
/** The versionCode that was read from app's local.properties. */
String flutterVersionCode = null
/** The versionName that was read from app's local.properties. */
String flutterVersionName = null
/** Returns flutterVersionCode as an integer with error handling. */
Integer versionCode() {
if (flutterVersionCode == null) {
throw new GradleException("flutterVersionCode must not be null.")
}
if (!flutterVersionCode.isNumber()) {
throw new GradleException("flutterVersionCode must be an integer.")
}
return flutterVersionCode.toInteger()
}
/** Returns flutterVersionName with error handling. */
String versionName() {
if (flutterVersionName == null) {
throw new GradleException("flutterVersionName must not be null.")
}
return flutterVersionName
}
} }
// This buildscript block supplies dependencies for this file's own import // This buildscript block supplies dependencies for this file's own import
...@@ -226,7 +254,28 @@ class FlutterPlugin implements Plugin<Project> { ...@@ -226,7 +254,28 @@ class FlutterPlugin implements Plugin<Project> {
// Load shared gradle functions // Load shared gradle functions
project.apply from: Paths.get(flutterRoot.absolutePath, "packages", "flutter_tools", "gradle", "src", "main", "groovy", "native_plugin_loader.groovy") project.apply from: Paths.get(flutterRoot.absolutePath, "packages", "flutter_tools", "gradle", "src", "main", "groovy", "native_plugin_loader.groovy")
project.extensions.create("flutter", FlutterExtension) def extension = project.extensions.create("flutter", FlutterExtension)
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"
}
extension.flutterVersionCode = flutterVersionCode
def flutterVersionName = localProperties.getProperty("flutter.versionName")
if (flutterVersionName == null) {
flutterVersionName = "1.0"
}
extension.flutterVersionName = flutterVersionName
this.addFlutterTasks(project) this.addFlutterTasks(project)
// By default, assembling APKs generates fat APKs if multiple platforms are passed. // By default, assembling APKs generates fat APKs if multiple platforms are passed.
......
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