web-dev-qa-db-fra.com

Copier le fichier APK dans le projet Android Gradle

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.

42
Graham Borland

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.

28
Xavier Ducrohet

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:

  • release - Assemble et archive toutes les versions de Release
  • releaseFree - Assemble et archive toutes les versions de Release pour flavour Free
  • releaseFreeRelease - Assemble et archive apk et sa cartographie de proguard pour la construction de FreeRelease
  • releasePaid - Assemble et archive toutes les versions de Release pour le goût payé
  • releasePaidRelease - Assemble et archive apk et sa cartographie de proguard pour la compilation PaidRelease

Le contenu de l’archive/nomprojet/packageName-buildType-versionName_versionCode.Zip serait:

  • packageName-buildType-versionName_versionCode.apk
  • packageName-buildType-versionName_versionCode-proguard_mapping.txt
9
Ladios Jonquil

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]
                }
            }
        }
    }
}
6
saulobrito

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"
        }

    } 
}
6
martinpelant
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
    }
}
4
ipcjs

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:

  • APP-debug-unaligned.apk
  • APP-release-unaligned.apk
  • APP-release-unsigned.apk
  • APP-release.apk Etc
0
cbrulak