在Android Gradle项目中复制APK文件

Gra*_*and 43 android gradle android-gradle-plugin

我正在尝试将自定义任务添加到我的Android项目中,build.gradle以将最终的APK和Proguard复制mapping.txt到另一个目录中.我的任务取决于assembleDevDebug任务:

task publish(dependsOn: 'assembleDevDebug') << {
    description 'Copies the final APK to the release directory.'

    ...
}
Run Code Online (Sandbox Code Playgroud)

Copy根据文档,我可以看到如何使用标准任务类型执行文件复制:

task(copy, type: Copy) {
    from(file('srcDir'))
    into(buildDir)
}
Run Code Online (Sandbox Code Playgroud)

但这假设您知道要复制的文件的名称和位置.

如何找到作为assembleDevDebug任务一部分构建的APK文件的确切名称和位置?这可以作为财产吗?感觉好像我应该能够将文件声明为我的任务的输入,并将它们声明为assemble任务的输出,但我的Gradle-fu不够强大.

我有一些自定义逻辑将版本号注入APK文件名,所以我的publish任务不能只假设默认名称和位置.

Xav*_*het 27

如果您可以获取与devDebug关联的变体对象,则可以使用getOutputFile()查询它.

因此,如果您想要发布所有变体,您可以这样:

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
}
Run Code Online (Sandbox Code Playgroud)

现在你可以打电话gradle publishAll,它会发布你所有的变种.

映射文件的一个问题是Proguard任务没有为您提供文件位置的getter,因此您当前无法查询它.我希望能解决这个问题.

  • 我得到`错误:(270,0)无法在com.android.build.gradle.internal.api.ApplicationVariantImpl_Decorated @ 4be85d24上找到属性'outputFile'. (3认同)
  • relpace:`variant.outputs [0] .outputFile` (2认同)

小智 9

以下代码是我用来将apk和proguard映射存档到zip文件中的每个变体的'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
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

它创建如下任务:

  • 发布 - 汇总和归档所有发布版本
  • releaseFree - 汇总和归档所有版本版本,以免味道
  • releaseFreeRelease - Assembles and archives apk及其FreeRelease构建的proguard映射
  • releasePaid - 为所有版本Paid组装和归档所有版本构建
  • releasePaidRelease - 用于PaidRelease构建的Assembles和archives apk及其proguard映射

archive/projectName/packageName-buildType-versionName_versionCode.zip的内容将是:

  • 的packageName-buildType-versionName_versionCode.apk
  • 的packageName-buildType-versionName_versionCode-proguard_mapping.txt


mar*_*ant 6

这是我在proguard运行时复制mappings.txt的方法

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

    } 
}
Run Code Online (Sandbox Code Playgroud)


sau*_*ito 6

我在这里有一些好的指示,但也很难按我的意愿完成.这是我的最终版本:

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]
                }
            }
        }
    }
}
Run Code Online (Sandbox Code Playgroud)