20949

Set Android versionCode after Gradle task completes

Question:

I have a task that updates my app's version code, called <em>changeVersionCode</em>. This task runs before my Android build tasks (<em>assembleRelease</em>), but obviously it happens after the android { } closure. This seems to mean that versionCode is set and cannot be changed even when <em>changeVersionCode</em> runs.

Here's a simplified build script that demonstrates how I have tried to approach this problem:

// .version is a file that starts at "1" the first time I call this def loadVersionCode() { // fetch version code from a file, '.version' return loadVersionCodeFromFile('.version') } def incrementVersionCode() { // fetch version code, update it, and save it back to a file def newVersion = loadVersionCode() + 1 saveVersionCodeToFile('.version', newVersion) } apply plugin: 'com.android.application' android { // ... snip ... defaultConfig { // Set the version code to contents of .version (eg. 1) versionCode loadVersionCode() // ... } } task incrementVersionCode << { println "Old version code: " + android.defaultConfig.versionCode // prints 1 incrementVersionCode() def newVersion = loadVersion() // this now returns 2 android.defaultConfig.versionCode = loadVersionCode() // Also tried: // android.defaultConfig.versionCode loadVersionCode() println "New version code: " + android.defaultConfig.versionCode // prints 2 // android.defaultConfig.versionCode is now 2, but APK still has version 1 (until next time I run gradle) }

Then:

# Build an APK with versionCode 1 $ ./gradlew assembleRelease # This seems to change versionCode to 2, but still builds an APK with versionCode 1 # # Prints: # Old version code: 1 # New version code: 2 $ ./gradlew incrementVersionCode assembleRelease

I am using:

<ul><li>Gradle 2.5</li> <li>Groovy 2.3.10</li> <li>Ant 1.9.3</li> <li>Java 1.8.0_45</li> <li>Mac OS X 10.10.5</li> <li>Android build tools 22.0.1</li> </ul>

Is there any way I can change my version code from a task before invoking Android build tasks?

Answer1:

<strong>How to configure versionCode before a task is launched</strong>

You can use the DSL tasks.whenTaskAdded. You can read the <a href="https://docs.gradle.org/current/userguide/build_lifecycle.html" rel="nofollow">official doc</a>, chapter 58.6.2. Task creation.

<blockquote>

You can receive a notification immediately after a task is added to a project. This can be used to set some default values or add behaviour <strong>before the task</strong> is made available in the build file.

</blockquote>

You can define a task:

task incrementVersionCode << { //do something }

Then define the dependency :

tasks.whenTaskAdded { task -> if (task.name == 'xxxxx') { task.dependsOn incrementVersionCode } }

In your case you can do somenthing like this:

tasks.whenTaskAdded { task -> if (task.name == 'generateReleaseBuildConfig' || task.name == 'generateDebugBuildConfig') { task.dependsOn 'increaseVersionCode' } }

<strong>How to configure versionCode with a function</strong>

In the top-level file you can configure a function like this:

ext { buildVersionCode = { //... } }

In your module/build.gradle you can do somehing like this:

defaultConfig { versionCode buildVersionCode() //.... }

Otherwise you can do in your build.gradle something like:

defaultConfig { //... versionCode getMyNumber() } def getMyNumber() { return //.... ; }

Recommend

  • FOSRestBundle + Symfony 3.4 : rest type not reconized
  • Unable to access controls inside JuiceUI dialog
  • Android SQlite not updating the data
  • Programmatically center text output in for loop
  • llvm::DIInstruction getFilename returns filename with a directory, I just want the filename
  • Prevent floating DIVs from overlapping footer
  • Tests with generic classes crash since swift 2.2
  • Xamarin: Couldn't find “libmonodroid.so” emulator error
  • Gradle Build Failure java.io.IOException: The output jar is empty
  • Error ':app:packageAllDebugClassesForMultiDex'. > java.util.zip.ZipException: duplicate
  • exception android.support.multidex.MultiDexApplication cannot be cast class
  • Android Sqlite Problem
  • update google services from 9.0.0 to 10.0.1 Android studio 2.2
  • Change environment variable value between tasks in Build vNext
  • getWritableDatabase() throwing null pointer exception in my apps
  • objective-c MPMoviePlayerViewController done button language
  • androidx android.support.v4.app.INotificationSideChannel$Stub
  • Pre-populated SQLite Database not reading properly in Android Studio
  • Any nice way to generate a timeline view of commits from subversion?
  • python: forcing relative imports to search from script file
  • jQuery - resize an elements height to match window without refreshing, on window resize
  • Jenkins Grails plugin does not list lastest versions of Grails
  • Iron Router: How do I send data to the layout?
  • Spring boot 2.0.0.M4 required a bean named 'entityManagerFactory' that could not be found
  • I18n locale disregarding fallbacks
  • How to generate and display a QR Code in ionic 2
  • Spring Cloud Microservice Architecture Confusion
  • WPF ICommand CanExecute(): RaiseCanExecuteChanged() or automatic handling via DispatchTimer?
  • Reduction and collapse clauses in OMP have some confusing points
  • Connect .sks to skscene.h
  • How do I access an unhandled exception in an MVC Error view?
  • MongoDb aggregation
  • iOS: Detect app start via notification press
  • How to use remove-erase idiom for removing empty vectors in a vector?
  • Spring Data JPA custom method causing PropertyReferenceException
  • C# - Serializing and deserializing static member
  • Sending data from AppleScript to FileMaker records
  • How to include full .NET prerequisite for Wix Burn installer
  • WPF Applying a trigger on binding failure
  • Is it possible to post an object from jquery to bottle.py?