【问题标题】:How to define apk output directory when using gradle?使用gradle时如何定义apk输出目录?
【发布时间】:2014-04-03 09:26:18
【问题描述】:

使用gradle时如何定义apk输出目录?

我希望能够在每次构建后将 apk 上传到共享文件夹。

【问题讨论】:

    标签: android-studio android-gradle-plugin


    【解决方案1】:

    这对我有用:

    android.applicationVariants.all { variant ->
        def outputName = // filename
        variant.outputFile = file(path_to_filename)
    }
    

    或者对于 Gradle 2.2.1+

    android {
        applicationVariants.all { variant ->
            variant.outputs.each { output ->
                output.outputFile = new File(path_to_filename, output.outputFile.name)
            }
        }
    }
    

    但是“clean”任务不会删除那个apk,所以你应该像下面这样扩展clean任务:

    task cleanExtra(type: Delete) {
        delete outputPathName
    }
    
    clean.dependsOn(cleanExtra)
    

    完整样本:

    apply plugin: 'android'
    
    def outputPathName = "D:\\some.apk"
    
    android {
        compileSdkVersion 19
        buildToolsVersion "19.0.3"
    
        defaultConfig {
            minSdkVersion 8
            targetSdkVersion 19
            versionCode 1
            versionName "1.0"
        }
        buildTypes {
            release {
                runProguard false
                proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.txt'
            }
        }
    
        applicationVariants.all { variant ->
            variant.outputFile = file(outputPathName)
        }
    }
    
    dependencies {
        compile 'com.android.support:appcompat-v7:19.+'
        compile fileTree(dir: 'libs', include: ['*.jar'])
    }
    
    task cleanExtra(type: Delete) {
        delete outputPathName
    }
    
    clean.dependsOn(cleanExtra)
    

    【讨论】:

    • 这不适用于 Gradle 2.2.1+ 版本:> 没有这样的属性:类的 outputFile:com.android.build.gradle.internal.api.ApplicationVariantImpl_Decorated
    • 这不适用于 Gradle 4.1:无法设置只读属性 'outputFile' 的值
    • 使用 Gradle 4.1:- 1. 使用“variant.outputs.all”代替“variant.outputs.each”,2. 使用“variant.outputFileName”代替“variant.outputFile”跨度>
    • 不能用 outputFileName 设置目录,可以吗?
    • 您不能使用 outputFileName 设置特定的目录/文件夹但是您可以在其中使用相对路径(例如“..\\..\\${buildType}\\${variant.flavorName} .apk"
    【解决方案2】:

    我找到了适用于最新 Gradle 插件的解决方案:

    def archiveBuildTypes = ["release", "debug"];
    
    applicationVariants.all { variant ->
        variant.outputs.each { output ->
            if (variant.buildType.name in archiveBuildTypes) {
                // Update output filename
                if (variant.versionName != null) {
                    String name = "MY_APP-${variant.versionName}-${output.baseName}.apk"
                    output.outputFile = new File(output.outputFile.parent, name)
                }
                // Move output into DIST_DIRECTORY
                def taskSuffix = variant.name.capitalize()
                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."
                        print "Copying APK&mappings.txt from: ${buildDir}\n"
                        from("${buildDir}") {
                            include "**/mapping/${variant.buildType.name}/mapping.txt"
                            include "**/apk/${output.outputFile.name}"
                        }
                        into DIST_DIRECTORY
                        eachFile { file ->
                            file.path = file.name // so we have a "flat" copy
                        }
                        includeEmptyDirs = false
                    }
                    tasks[assembleTaskName].finalizedBy = [copyAPKTask]
                }
            }
        }
    }
    

    【讨论】:

    • 这支持哪个版本?最新的 gradle 4.1 报告未知属性“archivedBuildTypes”。接下来是只读属性'outputFile'
    • 我的 gradle 构建失败并出现错误:Cannot set the value of read-only property 'outputFile' for ApkVariantOutputImpl_Decorated{apkData=Main{type=MAIN, fullName=oneOfMyVariantDebug, filters=[]}} of type com.android.build.gradle.internal.api.ApkVariantOutputImpl
    • @3c71 我认为你有错字。它不是 archivedBuildTypes 而是 archiveBuildTypes
    【解决方案3】:

    对于 Gradle 版本 2.2.1 +,您可以这样做:

    def outputPathName = "app/app-release.apk"
    applicationVariants.all { variant ->
            variant.outputs.each { output ->
                output.outputFile = new File(outputPathName)
            }
        }
    

    【讨论】:

    • 这不适用于 Gradle 4.1:无法设置只读属性“outputFile”的值。 Gradle 4.1 现在将 APK 保存在以变体命名的子文件夹中。
    【解决方案4】:

    此解决方案适用于 classpath 'com.android.tools.build:gradle:3.1.2'distributionUrl=https\://services.gradle.org/distributions/gradle-4.4-all.zip。将以下代码放入应用级build.gradle 文件的android 范围内。当您使用命令./gradlew assembleDebug./gradlew assembleRelease 时,输出文件夹将被复制到distFolder

    // Change all of these based on your requirements
    def archiveBuildTypes = ["release", "debug"];
    def distFolder = "/Users/me/Shared Folder(Personal)/MyApplication/apk/"
    def appName = "MyApplication"
    
    applicationVariants.all { variant ->
        variant.outputs.all { output ->
            if (variant.buildType.name in archiveBuildTypes) {
                // Update output filename
                if (variant.versionName != null) {
                    String name = "$appName-${variant.versionName}-${output.baseName}.apk"
                    outputFileName = new File(name)
                }
                def taskSuffix = variant.name.capitalize()
                def assembleTaskName = "assemble${taskSuffix}"
                if (tasks.findByName(assembleTaskName)) {
                    def copyAPKFolderTask = tasks.create(name: "archive${taskSuffix}", type: org.gradle.api.tasks.Copy) {
                        description "Archive/copy APK folder to a shared folder."
                        def sourceFolder = "$buildDir/outputs/apk/${output.baseName.replace("-", "/")}"
                        def destinationFolder = "$distFolder${output.baseName.replace("-", "/")}"
                        print "Copying APK folder from: $sourceFolder into $destinationFolder\n"
                        from(sourceFolder)
                        into destinationFolder
                        eachFile { file ->
                            file.path = file.name // so we have a "flat" copy
                        }
                        includeEmptyDirs = false
                    }
                    tasks[assembleTaskName].finalizedBy = [copyAPKFolderTask]
                }
            }
        }
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2023-03-31
      • 2019-06-26
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多