I'm trying to add a custom task to my Android project's build.gradle
to copy the final APK and Proguard's mapping.txt
into a different directory. My task depends on the assembleDevDebug
task:
task publish(dependsOn: 'assembleDevDebug') << { description 'Copies the final APK to the release directory.' ... }
I can see how to do a file copy using the standard Copy
task type, as per the docs:
task(copy, type: Copy) { from(file('srcDir')) into(buildDir) }
but that assumes you know the name and location of the file you want to copy.
How can I find the exact name and location of the APK file which was built as part of the assembleDevDebug
task? Is this available as a property? It feels as if I should be able to declare the files as inputs to my task, and declare them as outputs from the assemble
task, but my Gradle-fu isn't strong enough.
I have some custom logic to inject the version number into the APK filename, so my publish
task can't just assume the default name and location.
If you can get the variant object associated with devDebug you could query it with getOutputFile().
So if you wanted to publish all variants you'd something like this:
def publish = project.tasks.create("publishAll") android.applicationVariants.all { variant -> def task = project.tasks.create("publish${variant.name}Apk", Copy) task.from(variant.outputFile) task.into(buildDir) task.dependsOn variant.assemble publish.dependsOn task }
Now you can call gradle publishAll
and it'll publish all you variants.
One issue with the mapping file is that the Proguard task doesn't give you a getter to the file location, so you cannot currently query it. I'm hoping to get this fixed.
The following code is what I'm using to archive apk and proguard mapping into a zip file for each variant with 'release' build type:
def releasePath = file("${rootDir}/archive/${project.name}") def releaseTask = tasks.create(name: 'release') { group 'Build' description "Assembles and archives all Release builds" } android.applicationVariants.all { variant -> if (variant.buildType.name == 'release') { def build = variant.name.capitalize() def releaseBuildTask = tasks.create(name: "release${build}", type: Zip) { group 'Build' description "Assembles and archives apk and its proguard mapping for the $build build" destinationDir releasePath baseName variant.packageName if (!variant.buildType.packageNameSuffix) { appendix variant.buildType.name } if (variant.versionName) { version "${variant.versionName}_${variant.versionCode}" } else { version "$variant.versionCode" } def archiveBaseName = archiveName.replaceFirst(/\.${extension}$/, '') from(variant.outputFile.path) { rename '.*', "${archiveBaseName}.apk" } if (variant.buildType.runProguard) { from(variant.processResources.proguardOutputFile.parent) { include 'mapping.txt' rename '(.*)', "${archiveBaseName}-proguard_\$1" } } } releaseBuildTask.dependsOn variant.assemble variant.productFlavors.each { flavor -> def flavorName = flavor.name.capitalize() def releaseFlavorTaskName = "release${flavorName}" def releaseFlavorTask if (tasks.findByName(releaseFlavorTaskName)) { releaseFlavorTask = tasks[releaseFlavorTaskName] } else { releaseFlavorTask = tasks.create(name: releaseFlavorTaskName) { group 'Build' description "Assembles and archives all Release builds for flavor $flavorName" } releaseTask.dependsOn releaseFlavorTask } releaseFlavorTask.dependsOn releaseBuildTask } } }
It creates tasks like the following:
Content of archive/projectName/packageName-buildType-versionName_versionCode.zip would be:
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