I'm trying to automatically update the versionName and VersionCode parameters in Android Manifest and use them in the output file name instead of "app-release.apk".
From this site I added this code in my build.gradle file:
import java.util.regex.Pattern
import com.android.builder.core.DefaultManifestParser
def mVersionCode
def mNextVersionName
def newName
task ('increaseVersionCode') << {
def manifestFile = file("src/main/AndroidManifest.xml")
def pattern = Pattern.compile("versionCode=\"(\\d+)\"")
def manifestText = manifestFile.getText()
def matcher = pattern.matcher(manifestText)
matcher.find()
mVersionCode = Integer.parseInt(matcher.group(1))
def manifestContent = matcher.replaceAll("versionCode=\"" + ++mVersionCode + "\"")
manifestFile.write(manifestContent)
}
task ('incrementVersionName') << {
def manifestFile = file("src/main/AndroidManifest.xml")
def patternVersionNumber = Pattern.compile("versionName=\"(\\d+)\\.(\\d+)\\.(\\d+)\\.(\\d+)\"")
def manifestText = manifestFile.getText()
def matcherVersionNumber = patternVersionNumber.matcher(manifestText)
matcherVersionNumber.find()
def majorVersion = Integer.parseInt(matcherVersionNumber.group(1))
def minorVersion = Integer.parseInt(matcherVersionNumber.group(2))
def pointVersion = Integer.parseInt(matcherVersionNumber.group(3))
def buildVersion = Integer.parseInt(matcherVersionNumber.group(4))
mNextVersionName = majorVersion + "." + minorVersion + "." + pointVersion + "." + (buildVersion + 1)
def manifestContent = matcherVersionNumber.replaceAll("versionName=\"" + mNextVersionName + "\"")
manifestFile.write(manifestContent)
}
tasks.whenTaskAdded { task ->
if (task.name == 'generateReleaseBuildConfig') {
task.dependsOn 'increaseVersionCode'
task.dependsOn 'incrementVersionName'
}
}
this code works perfectly, the 2 tasks run and correctly update the manifest file.
Now I want to use the 2 variables mVersionCode
and mNextVersionName
in the release
block inside the buildTypes
like this:
newName = defaultConfig.applicationId + "-" + mNextVersionName + " (" + mVersionCode + ").apk"
applicationVariants.all { variant ->
variant.outputs.each {output ->
def file = output.outputFile
output.outputFile = new File(file.parent, file.name.replace("app-release.apk", newName))
}
}
but the returned value of the 2 is null.
I also tried setting properties and extra properties:
task.setProperty("vName", mNextVersionName)
ext.vName = mNextVersionName
extensions.extraProperties.set("vName", mNextVersionName)
in the 2 tasks and getting them in the release
block without luck.
Does someone has ideas on how to accomplish this?
In Android Studio, you can configure your project to sign the release version of your app automatically during the build process by creating a signing configuration and assigning it to your release build type. A signing configuration consists of a keystore location, keystore password, key alias, and key password.
gradlew assembleRelease produces warnings for basic react-native app with enabled Hermes.
No one answered, but I found a working solution. I don't like it, it can be done in a better way, but for now is the only workaround I found.
I'm still looking for a better solution, if you have one, I'll be happy to read and use it instead of mine.
So, I added a new task in the gradle.build file, it just do a copy of the 'app-release.apk' file and rename it using the values in the manifest file:
task copia{
dependsOn('assembleRelease')
def manifestFile = file("src/main/AndroidManifest.xml")
def patternVersionNumber = Pattern.compile("versionName=\"(\\d+)\\.(\\d+)\\.(\\d+)\\.(\\d+)\"")
def manifestText = manifestFile.getText()
def matcherVersionNumber = patternVersionNumber.matcher(manifestText)
matcherVersionNumber.find()
def majorVersion = Integer.parseInt(matcherVersionNumber.group(1))
def minorVersion = Integer.parseInt(matcherVersionNumber.group(2))
def pointVersion = Integer.parseInt(matcherVersionNumber.group(3))
def buildVersion = Integer.parseInt(matcherVersionNumber.group(4))
def mVersionName = majorVersion + "." + minorVersion + "." + pointVersion + "." + (buildVersion)
def pattern = Pattern.compile("versionCode=\"(\\d+)\"")
def matcher = pattern.matcher(manifestText)
matcher.find()
def myVersionCode = Integer.parseInt(matcher.group(1))
copy {
from 'app-release.apk'
rename { String fileName ->
fileName.replace('app-release.apk', 'com.walker93.catpadova-' + mVersionName + ' (' + myVersionCode + ').apk')
}
into 'apk_outputs'
}
}
As you can see it's just a copy and edited version of the code in the 2 previous tasks with a copy {}
function (here the docs), it reads the versionName and versionCode values without increment them, then it put them in the new filename i'm going to replace.
This task still requires the 2 other task to be there, so finally you will have 3 tasks.
In the first line of this task there is dependsOn(assembleRelease)
. This is very important, it will run all the others default release build tasks (included our 2 tasks that increment and write in the manifest) that generate the updated and signed apk.
Now if you try to run the "generate signed APK..." you will notice that this task will not run. Instead you will have to manually launch it:
Add your task in the "run configurations" like this and then you should be able to run the task from here or here when you want to publish the signed apk with the custom name. If you want to generate a signed apk with default name (and still increment versionName and versionCode) just use the "generate signed APK..." option like before.
Using this method there is no need to add code in the buildTypes
part of the file.
Allright, here is my code of build.gradle
of application module :
apply plugin: 'com.android.application'
apply from: 'versionalization.gradle'
def genVersionName = VersionInfo.versionName
def genVersionCode = VersionInfo.versionCode
android {
compileSdkVersion 22
buildToolsVersion "22.0.1"
defaultConfig {
applicationId "com.vincestyling.exerciseapk"
minSdkVersion 10
targetSdkVersion 22
versionName genVersionName
versionCode genVersionCode
}
}
android.applicationVariants.all { variant ->
def taskSuffix = variant.name.capitalize()
def assembleTaskName = "assemble${taskSuffix}"
if (tasks.findByName(assembleTaskName)) {
def processAPKTask = tasks.create(name: "process${taskSuffix}Apk", type: Copy) {
variant.outputs.each { output ->
from output.outputFile
into output.outputFile.parent
def newApkName = android.defaultConfig.applicationId + "-" + variant.buildType.name + "-" + genVersionName + " (" + genVersionCode + ").apk"
rename ~/(.+)/, newApkName
}
}
tasks[assembleTaskName].finalizedBy processAPKTask
}
}
the versionalization.gradle
which applied at head is what I use to increase the VersionInfo, then return two values to use.
task VersionInfo {
String FACTOR_KEY = "BUILD_NUMBER_FACTOR"
File buildDir = file("build")
buildDir.mkdir()
File factorPropFile = new File(buildDir, "kbuildfactor.prop")
Properties props = new Properties()
if (factorPropFile.exists()) {
props.load(new FileInputStream(factorPropFile))
}
int buildNumberFactor = props.get(FACTOR_KEY) as Integer ?: 0
buildNumberFactor += 1
props.put(FACTOR_KEY, buildNumberFactor as String)
props.store(new FileOutputStream(factorPropFile), null)
String BASE_VERSION_NAME = "BASE_VERSION_NAME"
String BASE_VERSION_CODE = "BASE_VERSION_CODE"
File versionPropFile = file("versioning.properties")
props.load(new FileInputStream(versionPropFile))
String baseVersionName = props.get(BASE_VERSION_NAME) as String
Integer baseVersionCode = props.get(BASE_VERSION_CODE) as Integer
ext.versionName = baseVersionName + "." + buildNumberFactor
ext.versionCode = baseVersionCode * 1000 + buildNumberFactor
}
it's quite straightforward, read two files to take the necessary fields to constructing the version informations.
we copy/rename the final APK at last.
besides, I achieved the copy/rename part as below first, but it won't work when you have any product flavors, I paste here as another choice.
android.applicationVariants.all { variant ->
variant.outputs.each {output ->
def newApkName = android.defaultConfig.applicationId + "-" + variant.buildType.name + "-" + genVersionName + " (" + genVersionCode + ").apk"
def oldApkName = "app-${variant.buildType.name}.apk"
def file = output.outputFile
output.outputFile = new File(file.parent, file.name.replace(oldApkName, newApkName))
}
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With