I have an Android that I deploy to a Google Play alpha track trough a CI server. For the Android versionCode I make use of the CI build number that I inject into the Gradle script through an environment variable.
This used to work fine; but currently Google Play is not accepting any builds. When I manually trigger a alpha upload build (using the gradle-play-publisher plugin) for Gradle I eventually end up with the following error:
APK has an invalid version code.
So when looking (using aapt dump badging apk-path) at the generated APK I see an empty value for the version code (versionCode='').
The relevant code from the build script:
def appVersionCode = System.getenv("BUILD_NUMBER") as Integer ?: 0
defaultConfig {
...
versionCode appVersionCode
...
}
It seems the variable is not read correctly; however it reads System.getenv("KEY_PASS") correctly to use for signing.
The variable is also set:
❯ echo $BUILD_NUMBER
1234
Does anyone have an idea why this specific variable doesn't seem to be read (anymore)?
Gradle version: 3.5 with Android Gradle plugin 2.3.1.
Try to change your code to this:
def appVersionCode = Integer.valueOf(System.env.BUILD_NUMBER ?: 0)
defaultConfig {
...
versionCode appVersionCode
...
}
Related
How should I increase my version number in an android project, as a step of build pipeline app center deployment? Does the Azure DevOps has a version manager plugin, or should I create a version.properties file and edit, commit, push into the current branch?
Build pipeline:
This can be done more clean with out using the properties file and then replacing that using a shell script.
In the top level build.gradle file, under the build scripts:
buildscript {
def getVersionCode = { ->
def code = project.hasProperty('versionCode') ? versionCode.toInteger() : -1
println "VersionCode is set to $code"
return code
}
def getVersionName = { ->
def name = project.hasProperty('versionName') ? versionName : "1.0"
println "VersionName is set to $name"
return name
}
ext{
versionCode = getVersionCode()
versionName = getVersionName()
}
}
In your module specific gradle file :
defaultConfig {
versionCode rootProject.ext.versionCode
versionName rootProject.ext.versionName
}
In your Devops pipeline for the gradle build task, just pass on the options like so:
-PversionName=$(Build.BuildNumber) -PversionCode=$(Build.BuildId)
Unfortunately is no out of the box support, but you can find here a good tutorial:
Install Colin's ALM Corner Build & Release Tools that include Version Assemblies task.
In the Android manifest the name and code should look like this:
android:versionCode="1" android:versionName="1.0.0"
Add the “Version Assemblies” task TWICE, once for the version name and once for the version code.
Once added, we will bump the name.
First insert the following (with examples):
Source Path: src/MobileApps/MyDriving/MyDriving.Android/Properties
File Pattern: AndroidManifest.xml
Build Regex Pattern: (?:\d+.\d+.\d+.)(\d+)
Under Advanced:
Build Regex Group Index: 0
Regex Replace Pattern: versionName=“\d+.\d+.\d+
Prefix for Replacements: versionName=”
What this will do is update the version name to the Build number format found under “General”, which mine is set to 1.0.0$(rev:.r)
Now for the next one, which is the version code:
Source Path: src/MobileApps/MyDriving/MyDriving.Android/Properties
File Pattern: AndroidManifest.xml
Build Regex Pattern: (?:\d+.\d+.\d+.)(\d+)
Under Advanced:
Build Regex Group Index: 1
Regex Replace Pattern: versionCode=“\d+
Prefix for Replacements: versionCode\
And just like that you are good to go. This will simply update it with the current version revision :)
There is an existing task called
Mobile App Tasks for iOS and Android in the marketplace which was developed by James Montemagno
You can find the step-by-step instruction in the github
He has developed this task mainly to address this kind of versioning in both android/IOS Apps.
The best solution for me was make a version.properties file to track versioning and then modify it during the pipeline build process (shell script). The others are bad especially for custom versioning.
in an Android app I did not develop, but I have to edit, I found this gradle script:
buildscript {
repositories {
jcenter()
}
dependencies {
classpath 'org.ajoberstar:grgit:1.5.0'
}
}
import org.ajoberstar.grgit.Grgit
ext {
git = Grgit.open(currentDir: projectDir)
gitVersionName = git.describe()
gitVersionCode = git.tag.list().size()
gitVersionCodeTime = git.head().time
}
task printVersion() {
println("Version Name: $gitVersionName")
println("Version Code: $gitVersionCode")
println("Version Code Time: $gitVersionCodeTime")
}
The "gitVersionCode" variable is used as "versionCode" of the app in the build.gradle file.
This is the build.gradle file:
// gradle script
apply from: "$project.rootDir/tools/script-git-version.gradle"
//...
defaultConfig {
applicationId "..."
minSdkVersion 17
targetSdkVersion 25
versionCode gitVersionCode
versionName gitVersionName
testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
}
When I generate signed APK and try to add to beta version, I get the google error that "Version code already exists", but I do not know how to edit the version code of the app.
My questions are:
what this code actually does?
how to edit the version code of the app?
Git is a version control system. Your project appears to be stored in a Git repository.
Grgit is a Groovy library that works with Git. Your Gradle script is loading this library.
git is an instance of Grgit. git.tag.list() returns a list of the Git tags used in this repository. git.tag.list().size() returns the number of tags in that list.
So, this Gradle script is setting the versionCode to be the number of Git tags used in the project's Git repository.
how to edit the version code of the app?
Either:
Create another Git tag, such as by tagging the version that you are trying to release, or
Change versionCode gitVersionCode to stop using gitVersionCode and use some other numbering system
It appears to be using this library to query git, in order to generate the version name and version code. In terms of the version code, it looks like it's setting it depending on the number of git tags it finds. So, to bump the version code, do a git tag on your release commit.
If that doesn't suit, you could just do it manually and replace
versionCode gitVersionCode
with
versionCode 99
replacing "99" with whatever your version code should be.
In our Android project we want the filename of our APK to contain information such as the date, git branch name and short commit hash.
We've been setting this as part of our defaultConfig
android {
defaultConfig {
setProperty("archivesBaseName", "$projectName.$branchName.$date.$buildNumber.$versionCode-$versionName-$versionSha")
}
}
This works most of the time but our build sometimes fails with errors pointing to the value being stale (for example after switching branches). Forcing Gradle Sync in Android Studio usually fixes it.
So is there a better, more robust way of making sure that property stays up to date and forces a gradle sync, if necessary?
try to call clean.execute() before
android { ... }
it is the cheapest 'sync' task I can think of :)
clean.execute()
android {
defaultConfig {
setProperty("archivesBaseName", "$projectName.$branchName.$date.$buildNumber.$versionCode-$versionName-$versionSha")
}
}
I was having same issue, they were not always uptodate with the build.
I solved it by using:
project.ext.set("archivesBaseName", "myAppName");
under the defaultConfig block, and I stopped having the problem.
Not sure it will work for the branch, build number or date, but it's worth giving it a shot.
Here's my configs, including the defaultConfig Block. For my case I was only using a hard coded versionName and build Number (I call it versionCode because I set it in the manifest dynamically). But maybe you can tweak it to your needs:
defaultConfig {
minSdkVersion 15
targetSdkVersion 22
versionCode System.getenv("BUILD_NUMBER") as Integer ?: 0
versionName "6.2.5." + versionCode
}
project.ext.set("archivesBaseName", "myAppname" + defaultConfig.versionName);
If an error occurs during the build process, the Messages window appears to describe the issue. Gradle may recommend some command-line options to help you resolve the issue, such as --stacktrace or --debug. To use command-line options with your build process:
Open the Settings or Preferences dialog: On Windows or Linux, select
File > Settings from the main menu.
Navigate to Build, Execution,Deployment > Compiler.
In the text field next to Command-line Options, enter your command-line options.
Click OK to save and exit.
Gradle will apply these command-line options the next time you try building your app.
I have taken the information from this page.
I'm trying to automate build process on CI that I'm working with. I am able to call a curl and assign it some variables such as version code and names. Then CI (in my case Bitrise CI) catch it and starts Release build.
However, before that I want to set version code and version name based on what has been passed by curl into build.gradle file and then build process starts.
So, I'm thinking I can write a plugin/task that gets version code/name from a command line and then inject it in build.gradle file. A command like ./gradlew setVersion 1 1.0.
Threefore, by running this command from an script that I'll write, I will be able to run this gradle task and everyone from anywhere in the glob is able to create a release build by curl. Quite interesting :)
I am able to write a task similar to following code an put it into my main build.gradle file.
task setVersion << {
println versionCode
println versionName
}
and pass it some parameters via command line:
./gradlew -PversionCode=483 -PversionName=v4.0.3 setVersion
This is my output:
:setVersion
483
v4.0.3
BUILD SUCCESSFUL
Total time: 6.346 secs
So far so good. My question is how to set it in build.gradle file?
You can create methods to update the versionCode and versionName from the command line:
def getMyVersionCode = { ->
def code = project.hasProperty('versionCode') ? versionCode.toInteger() : -1
println "VersionCode is set to $code"
return code
}
def getMyVersionName = { ->
def name = project.hasProperty('versionName') ? versionName : "1.0"
println "VersionName is set to $name"
return name
}
Then in the android block:
defaultConfig {
applicationId "your.app.id"
minSdkVersion 15
targetSdkVersion 23
versionCode getMyVersionCode()
versionName getMyVersionName()
archivesBaseName = "YourApp-${android.defaultConfig.versionName}"
}
Then you can just call any task really:
./gradlew assembleDebug -PversionCode=483 -PversionName=4.0.3
Read more about it here: https://web.archive.org/web/20160119183929/https://robertomurray.co.uk/blog/2013/gradle-android-inject-version-code-from-command-line-parameter/
I found a clean way that is compatible with CI tools (without edit your code):
./gradlew assembleDebug -Pandroid.injected.version.code=1234 -Pandroid.injected.version.name=1.2.3.4
there are more params here for other things like signing:
https://www.javadoc.io/static/com.android.tools.build/builder-model/2.5.0-alpha-preview-02/constant-values.html
For GitLab CI:
I use this command for a debug version:
./gradlew assembleDebug -Pandroid.injected.version.code=$CI_PIPELINE_IID -Pandroid.injected.version.name=$CI_COMMIT_SHORT_SHA
You can echo $CI_PIPELINE_IID if you want to know its number. It increases every time you run a new pipeline for your project.
And for a release version:
./gradlew assembleRelease -Pandroid.injected.signing.store.file=$SIGNING_STORE_FILE -Pandroid.injected.signing.store.password=$SIGNING_STORE_PASSWORD -Pandroid.injected.signing.key.alias=$SIGNING_KEY_ALIAS -Pandroid.injected.signing.key.password=$SIGNING_KEY_PASSWORD -Pandroid.injected.signing.v1-enabled=true -Pandroid.injected.signing.v2-enabled=true -Pandroid.injected.version.code=$CI_PIPELINE_IID -Pandroid.injected.version.name=$CI_COMMIT_TAG
Note: first 4 env vars are set in my project variables and are not internal gitlab ci variables!
Currently we have Bamboo listening to a Git repository on any changes. When a change occur the build process starts and increases the (Bamboo) build number by one.
I thought it would be nice to use this same build number for the Android project (versionCode) so that the user of the app can always refer to the actual build he/she received. This way the build number goes from 1 to 2 on the build server. Only the workstation doesn't know about this and still uses version 1.
Is there any way to sync this build number?
Tried:
One possible solution a friend of mine suggested was to use a git command to get the commit number: git rev-list HEAD --count which is awesome. The only downside of this is that you cannot properly change build number within Bamboo. So the build number of Bamboo should be leading.
Btw, I'm using Android Studio with Gradle
Bamboo can be configured to set the versionCode value in the manifest to the build number when building, so propagating this change back to where the development is happening should be unnecessary. To configure Bamboo to do this, add a Script task to the build plan (before the actual build task) with a body of:
sed -i 's/android:versionCode="[[:digit:]]*"/android:versionCode="${bamboo.buildNumber}"/' AndroidManifest.xml
Yes, it is quite easy with gradle. You have to retrieve the latest build result in the gradle script and put it in the versionCode.
Here it is what you need (remember to change the variables to refer your server):
def getBambooNumber(){
def url = "https://bambooServer:bambooPort/rest/api/latest/result/PROJECT-BAMBOO-ID/latest.json?os_authType=basic".toURL()
def authValue = "USER:PASSWORD".bytes.encodeBase64().toString()
def json = new JsonSlurper().parseText(url.getText(requestProperties : ["Authorization" : "Basic " + authValue]))
return json.buildNumber + 1 // +1 to Get the new build number
}
def bambooBuild = bambooBuildNumber()
android {
...
defaultConfig {
...
versionCode bambooBuild
//This allows you to access in BuildConfig to the bamboo build
buildConfigField "Integer", "BAMBOO_BUILD", "${bambooBuild}"
...
}
...
}
Let me know if this works for you.