Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Copying APK file in Android Gradle project

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.

like image 971
Graham Borland Avatar asked Jan 29 '14 14:01

Graham Borland


2 Answers

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.

like image 197
Xavier Ducrohet Avatar answered Oct 05 '22 20:10

Xavier Ducrohet


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:

  • release - Assembles and archives all Release builds
  • releaseFree - Assembles and archives all Release builds for flavor Free
  • releaseFreeRelease - Assembles and archives apk and its proguard mapping for the FreeRelease build
  • releasePaid - Assembles and archives all Release builds for flavor Paid
  • releasePaidRelease - Assembles and archives apk and its proguard mapping for the PaidRelease build

Content of archive/projectName/packageName-buildType-versionName_versionCode.zip would be:

  • packageName-buildType-versionName_versionCode.apk
  • packageName-buildType-versionName_versionCode-proguard_mapping.txt
like image 30
Ladios Jonquil Avatar answered Oct 05 '22 19:10

Ladios Jonquil