Renaming gradle apk output file, but there are 2 apks - android

I am trying to name my application's APK file based on the git branch, which is working by passing a parameter in with jenkins. However, I end up with two APKs, and this is undesirable because one of the Gradle tasks I have uploads the APK to a distributed list. The whole point of renaming this APK is so that people who receive it know exactly what branch they are seeing.
buildTypes {
...
feature {
signingConfig signingConfigs.debug
applicationVariants.all { variant ->
appendVersionNameVersionCode(variant, defaultConfig)
}
}
...
}
...
def appendVersionNameVersionCode(variant, defaultConfig) {
//check if staging variant
if(variant.name == android.buildTypes.feature.name){
def branch = hasProperty('branch') ? branch.replaceAll('origin/', '') : "UNKNOWN"
def file = variant.packageApplication.outputFile
def fileName = "myapp-FEATURE-" + branch + ".apk"
variant.packageApplication.outputFile = new File(file.parent, fileName)
}
}
Then the gradle command is invoked:
gradle assembleFeature --project-dir=/Path/To/myapp/ -Pbranch=origin/development
The two files that are generated from that are:
app-feature.apk
myapp-FEATURE-development.apk
File 1 is not desired, and I would ultimately want to rename that file, instead of generating a new file which is File 2.
Any thoughts?

Turns out, gradle always packages up 2 apks. One that is aligned, and one that isn't.
In order to rename the aligned apk file, I had to add this:
if (variant.zipAlign) {
newName = "myapp-FEATURE-" + branch + "-ALIGNED.apk"
variant.outputFile = new File(file.parentFile, newName);
}

Related

How do I unzip apk after build with different build variants?

I am struggling with writing a task which will unzip an apk. I have several Build Variants, and I want to dynamically create a task for each of them.
applicationVariants.all { variant -> variant.outputs.all { output ->
def assembleTaskName = 'assemble' + variant.getName().capitalize()
def outputDir = new File(output.packageApplication.outputDirectory.toString() + "\\tmp")
def apk = output.outputFile //there is some code which generates correct apk name based on Build Variant
tasks.getByName(assembleTaskName).finalizedBy(task("unzip" + apk.name, type: Zip) {
outputDir.mkdirs()
from zipTree(apk)
into outputDir
})
}}
While this code creates tmp folder where I need it, apk doesn't get extracted, and this code seems to run on every build variant I have, but I only need it to run on the one I build right now. How can I do that?

How to set up a task that does something to APKs built by Gradle?

I need to set up a custom task that I run after an APK is built when using Gradle for Android. Right now I actually have two tasks. One builds an XML file using the path to the APK as an input, and the other runs after the XML task (named packageConfig) and bundles the APK and the XML file into a ZIP.
Right now, I'm having trouble with my packageConfig task. It runs the python script for only the "fullRelease" product flavor, when I actually have multiple:
x86Debug
x86Release
armDebug
armRelease
fullDebug
fullRelease
My script is only executed once, and for the wrong APK. For example, I will invoke gradle like so:
$ gradlew :Applications:zApp:assemblex86debug packageConfig
I set up a print() call in my python script to output the APK path passed in, and it is:
build\outputs\apk\full\release\zApp.apk
The path I'm expecting (based on the product flavor I chose on the command line, as well as the APK I know that is there):
build\outputs\apk\x86\debug\zApp.apk
I'll paste my gradle task below. Can anyone help me understand what I'm doing wrong? What corrections can I make to my script to get it to run my script on the correct APK?
task packageConfig(type: Exec) {
def buildCommit = getBuildCommit()
def buildBranch = getVcsBranchName()
def buildDescription = buildBranch + '-' + buildCommit
def buildDate = getBuildDate()
workingDir buildscript.sourceFile.parent
android.applicationVariants.all { variant ->
variant.outputs.all { output ->
def apk = output.outputFile
def apkDir = apk.getParent();
def inputConfig = '' + project.projectDir + File.separator +
packageConfigXmlFile
def outputConfig = apkDir + File.separator + 'PackageConfig.xml'
commandLine 'python', 'setup-package-config.py', versions.version, inputConfig,
outputConfig, apk, buildDescription
}
}
}

Generate APK with declared name in Gradle without any suffixes

I know that it is possible to specify APK name by using following command in Gradle build file:
setProperty("archivesBaseName", "something")
There are lots of questions here that deal with this. But doing this also results in APK that has flavor and build variant appended to the name. So using above command results in APK that's named something-dev-debug.apk.
Is there a way to completely specify file name without appending any suffixes. I already have appId in my flavors like this:
//...
productFlavors {
dev {
applicationId "com.myapp.dev"
setProperty("archivesBaseName", applicationId)
}
//...
So ideally I would like to produce APK named com.myapp.dev.apk without any extra suffixes or version numbers. Is this possible?
It seems that this shouldn't be done with setPropery. Rather you can define handler that changes output file name as final step by adding following code to the end of android { } section in gradle file:
applicationVariants.all { variant ->
variant.outputs.each { output ->
def file = output.outputFile
def appId = variant.applicationId
def fileName = appId +".apk"
output.outputFile = new File(file.parent, fileName)
}
}

Change apk output folder in Gradle 4.1

I would like to change the APK output folder and this is what I used to do:
applicationVariants.all { variant ->
variant.outputs.all {
def filePath = "${rootProject.rootDir.absolutePath}/apks/${variant.name}"
println("My Path: " + filePath)
outputFileName = filePath
}
}
However, it didn't work in Gradle 4.1 (Android studio 3.0 preview). Instead of generating the folder as the path above, it generated the above path inside old debug folder like image below:
Does anyone have a solution for this? Thanks.
This is a workaround to keep the output path same after upgrade to gradle 4.x.
applicationVariants.all { variant ->
variant.outputs.all {
outputFileName = "../" + outputFileName
}
}
now apk is generated at platforms/android/build/outputs/apk/android-release.apk
From migration guide:
Using the Variant API to manipulate variant outputs is broken with the new plugin. It still works for simple tasks, such as changing the APK name during build time, as shown below:
android.applicationVariants.all { variant ->
variant.outputs.all {
outputFileName = "${variant.name}-${variant.versionName}.apk"
}
}
However, more complicated tasks that involve accessing outputFile objects no longer work. That's because variant-specific tasks are no longer created during the configuration stage. This results in the plugin not knowing all of its outputs up front, but it also means faster configuration times.
I had a similar issue, because I needed the output apk in a known folder and not in a folder depending on the computer user name. So I have fixed like this:
applicationVariants.all { variant ->
variant.outputs.all {
def apk = output.outputFile;
def newName = apk.name.replace(".apk", "-v" + variant.versionName + "-RELEASE.apk");
newName = newName.replace("-" + variant.buildType.name, "");
outputFileName = "./" + newName
}
}
With this I get the apk in:
".../outputs/apk/flavorName/buildTypeName/xxx.apk"
Hope it helps you.

Android gradle build config - Rename generated APKs

I need to save each APK with a special name whenever I build one.
This is the desired name format: "buildType appName_version_Date_Time.apk"
Example: "debug myAppName_v1.0_20161009_0854.apk"
Example: "release myAppName_v1.0_20161009_0854.apk"
For this purpose I added this gradle script:
buildTypes {
release {
minifyEnabled true
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
signingConfig signingConfigs.release
}
debug {
}
applicationVariants.all { variant ->
variant.outputs.each { output ->
def formattedDate = new Date().format('yyyyMMdd_HHmm')
println(output.outputFile)
def newName = variant.name + " myAppName_v" + defaultConfig.versionName + "_" + formattedDate + ".apk"
output.outputFile = new File(output.outputFile.parent, newName)
}
}
}
This script works, but android studio couldn't find the renamed APK. I also tried clean/rebuild project but it ocures again.
Android stuio error:
The APK file path\to\project\app\build\outputs\apk\debug myAppName_v1.0_[20161009_0854].apk does not exist on disk.
Error while Installing APK
When I check "build\outputs\apk" directory i see that an APK has been built and its name is "myAppName_v1.0_[20161009_0856].apk".
What's wrong here??
Instead of including the current time (with minutes, no less) in the APK filename, consider the following approaches:
Take the timestamp of the latest version control commit (that stays stable)
Instead of changing the apk filename, copy it from it's non-timestamped name - that Android Studio will easily find - to a timestamped apk.
Here's an example to try (haven't run it but should give the general idea). Choose either Files.copy or the copy task, not both.
applicationVariants.all { variant ->
variant.outputs.each { output ->
def copyApkTask = tasks.create(name: "copy" + variant.name + "Apk") {
def newName = ... // can include the timestamp with minutes
println(newName)
// Using java.nio.Files.copy
def targetPath = new File(output.outputFile.parent, newName).toPath()
Files.copy(output.outputFile.toPath(), targetPath)
// Using gradle's Copy logic (clunky for single-file copy and rename)
copy {
from output.outputFile
into output.outputFile.parent
rename { String fileName ->
newName
}
}
}
copyApkTask.mustRunAfter variant.assemble
}
}
you are telling gradle to include the minute in the name of your apk.
then it builds it with the name you want in the n minute, and when it wants to refer to it in the n+1 minute it cant find the file. so it encounters this error.
you better use the commit hash or the date in your apk name. (not including small units like minute or second or even hour)

Categories

Resources