J'essaie d'ajouter une tâche personnalisée au build.gradle
de mon projet Android pour copier le fichier APK final et le mapping.txt
de Proguard dans un répertoire différent. Ma tâche dépend de la tâche assembleDevDebug
:
task publish(dependsOn: 'assembleDevDebug') << {
description 'Copies the final APK to the release directory.'
...
}
Je peux voir comment faire une copie de fichier en utilisant le type de tâche Copy
standard, conformément à la documentation:
task(copy, type: Copy) {
from(file('srcDir'))
into(buildDir)
}
mais cela suppose que vous connaissiez le nom et l'emplacement du fichier que vous souhaitez copier.
Comment trouver le nom et l'emplacement exact du fichier APK construit dans le cadre de la tâche assembleDevDebug
? Est-ce disponible en tant que propriété? Il me semble que je devrais pouvoir déclarer les fichiers en tant qu'entrées dans ma tâche et les déclarer en tant que sorties de la tâche assemble
, mais mon Gradle-fu n'est pas assez puissant.
J'ai une logique personnalisée pour injecter le numéro de version dans le nom de fichier APK. Par conséquent, ma tâche publish
ne peut pas simplement assumer le nom et l'emplacement par défaut.
Si vous pouvez obtenir l'objet variant associé à devDebug, vous pouvez l'interroger avec getOutputFile ().
Donc, si vous voulez publier toutes les variantes, vous obtiendrez quelque chose comme ceci:
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
}
Maintenant, vous pouvez appeler gradle publishAll
et il publiera toutes vos variantes.
Un problème avec le fichier de mappage est que la tâche Proguard ne vous donne pas de getter à l'emplacement du fichier, vous ne pouvez donc pas l'interroger. J'espère résoudre ce problème.
Le code suivant est ce que j'utilise pour archiver les mappages apk et proguard dans un fichier Zip pour chaque variante avec le type de construction "release":
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
}
}
}
Il crée des tâches comme celles-ci:
Le contenu de l’archive/nomprojet/packageName-buildType-versionName_versionCode.Zip serait:
J'ai quelques bons indicateurs ici, mais j'ai également eu du mal à me faire faire ce que je voulais. Voici ma version finale:
def archiveBuildTypes = ["distribute"];
def archiveFlavors = ["googleplay"]
Android.applicationVariants.all { variant ->
if (variant.buildType.name in archiveBuildTypes) {
variant.productFlavors.each { flavor ->
if (flavor.name in archiveFlavors) {
def taskSuffix = variant.name.capitalize()
def version = "${Android.defaultConfig.versionCode} (${Android.defaultConfig.versionName})" // assumes that versionName was especified here instead of AndroidManifest.xml
def destination = "${rootDir}/${project.name}/archive/${version}"
def assembleTaskName = "assemble${taskSuffix}"
if (tasks.findByName(assembleTaskName)) {
def copyAPKTask = tasks.create(name: "archive${taskSuffix}", type:org.gradle.api.tasks.Copy) {
description "Archive/copy APK and mappings.txt to a versioned folder."
from ("${buildDir}") {
include "**/proguard/${flavor.name}/${variant.buildType.name}/mapping.txt"
include "**/apk/${variant.outputFile.name}"
}
into destination
eachFile { file->
file.path = file.name // so we have a "flat" copy
}
includeEmptyDirs = false
}
tasks[assembleTaskName].finalizedBy = [copyAPKTask]
}
}
}
}
}
Voici comment je copie mappings.txt à chaque exécution de proguard
tasks.whenTaskAdded { task ->
if (task.name.startsWith("proguard")) {//copy proguard mappings
task << {
copy {
from buildDir.getPath() + "/proguard"
into '../proguard'
include '**/mapping.txt'
}
println "PROGUARD FILES COPIED"
}
}
}
def publish = project.tasks.create("publishAll")// publish all task
applicationVariants.all { variant ->
if (variant.buildType.name.equals("release")) {// Only Release
File outDir = file("//192.168.4.11/Android/Release")
File apkFile = variant.outputs[0].outputFile
File mapFile = variant.mappingFile
def task = project.tasks.create("publish${variant.name.capitalize()}Apk", Copy)
task.from apkFile, mapFile
task.into outDir
task.rename "mapping.txt", "${apkFile.name.substring(0, apkFile.name.length() - 3)}mapping.txt"// Rename mapping.txt
task.doLast{
println ">>>publish ${variant.name} success!" +
"\ndir: ${outDir}" +
"\napk: ${apkFile.name}"
}
task.dependsOn variant.assemble
publish.dependsOn task
}
}
Habituellement, le plugin Android mettra les apks dans le répertoire APP/build/apk.
Donc, lancez assembleDebug
puis ls APP/build/apk
et vous devriez voir: