I have gradle task that depends on assembleRelease
sendReleaseCandidate.dependsOn assembleRelease
And I want to get resulted apk file path. From my task I've wrote:
def apk = android.applicationVariants.release.outputFile
But it doesn't work. What i'm doing wrong?
Thanks!
ps: android plugin 0.11.1, for now I stick with uri('./build/outputs/apk/<app_name>-release.apk').path but it seems aweful.
You can loop through the variants to find the one you need:
def apk = null
android.applicationVariants.all { variant ->
if ( (variant.name).equals("release") ) {
variant.outputs.each { output ->
apk = output.outputFile
}
}
}
println "Found output file: " + apk
Related
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?
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
}
}
}
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.
Prior to Android plugin version 3.0.0-alpha4, I have been using the following for publishing different variants of my APKs to a specific file path:
def publish = project.tasks.create("publishAll")
android.applicationVariants.all { variant ->
def task = project.tasks.create("publish${variant.name}Apk", Copy)
task.from(variant.outputs[0].outputFile)
task.into(buildDir)
task.dependsOn variant.assemble
publish.dependsOn task
}
I originally got it from this answer from Xavier Ducrohet: Copying APK file in Android Gradle project
As of the new updates to Android Studio Preview which uses version 3.0.0-alpha4, variant.outputFile is deprecated. What is the new suggested way to achieve something like this?
EDIT:
Looks like there is no way to currently access the variant output file as pointed out here: https://developer.android.com/studio/preview/features/new-android-plugin-migration.html#variant_api
Looks like we'll have to wait until they introduce those apis
If you don't use abi splits next snippet works
project.afterEvaluate {
android.applicationVariants.all { variant ->
// create file where to copy
def backupFolder = rootProject.file("backup")
def backupFile = new File(backupFolder, String.format("%s_v%s.%d.apk", variant.flavorName, variant.versionName, variant.versionCode))
variant.outputs.all { output ->
Task copyAndRenameAPKTask = project.task("copyAndRename${variant.name.capitalize()}APK", type: Copy) {
from output.outputFile.getParent()
into backupFolder
include output.outputFileName
rename(output.outputFileName, backupFile.getName())
}
// if copyAndRenameAPKTask needs to automatically execute assemble before
copyAndRenameAPKTask.dependsOn(variant.assemble)
copyAndRenameAPKTask.mustRunAfter(variant.assemble)
// if assemble needs to automatically execute copyAndRenameAPKTask after
variant.assemble.finalizedBy(copyAndRenameAPKTask)
}
}
}
Is it possible to specify the filename of the generated *.apk through gradle? So that I automatically could get MyApp-1.0.0.apk instead of the default app-release.apk.
You can do this by adding the following line to your build.gradle file inside the android{...} part:
android.applicationVariants.all { variant ->
variant.outputFile = file("$project.buildDir/${defaultConfig.versionName}-${defaultConfig.versionCode}.apk")
}
Notes:
Everything inside the file(...) is arbitrary, of course
This code will output the *.apk to your project/module/build directory, no matter what path you've specified when Building the Signed APK.
The output-file will take the Name and Version-Code from your build.gradle file.
Android Studio may complain that it "cannot resolve symbol applicationVariants/defaultConfig" - ignore it. ;)
Got it working! Used this answer
android {
applicationVariants.all { variant ->
variant.outputs.each { output ->
output.outputFile = new File(
output.outputFile.parent,
output.outputFile.name.replace(".apk", "-${variant.versionName}.apk"))
}
}
}