android studio 3.1: build:gradle:3.1.0 - Absolute path are not supported when setting an output file name
Asked Answered
T

9

19

When I use Android Studio 3.0 and I use the next version of Android Gradle Plugin in project/build.gradle:

classpath 'com.android.tools.build:gradle:3.0.1'

And it's work fine. After I update to Android Studio 3.1 , as result I update Android Gradle Plugin :

classpath 'com.android.tools.build:gradle:3.1.0'

And now I get error in my app/build.gradle:

def releaseFileName = "${rootProject.name}_${defaultConfig.versionName}.apk"
outputFileName = new File(rootProject.projectDir.absolutePath + "/release", releaseFileName.toLowerCase())

Error:

Absolute path are not supported when setting an output file name

I need to put output apk (app-release.apk) in specific path in project. In folder MyProject/release/app-relese.apk. How I can do this?

Tumulus answered 28/3, 2018 at 8:56 Comment(0)
W
16

I think using "./../../../" is bad solution... I use common gradle script for several projects and I want to make code to be independency from depth of output dir.

After some researching I found this solution for gradle plugin 3.1.2:

applicationVariants.all { variant ->
    variant.outputs.all { output ->
        def relativeRootDir = output.packageApplication.outputDirectory.toPath()
                 .relativize(rootDir.toPath()).toFile()
        output.outputFileName = new File( "$relativeRootDir/release", newOutputName)
    }
}
Weatherboard answered 14/6, 2018 at 16:32 Comment(1)
This does not work any more. This answer https://mcmap.net/q/113136/-android-studio-3-1-build-gradle-3-1-0-absolute-path-are-not-supported-when-setting-an-output-file-name is the simpler and working solution.Isauraisbel
J
25

Just in case this helps, this error means that now it's not allowed to have absolute paths on anything related to the apk's file name. I can attach you my BEFORE and AFTER to achieve what I needed (to have the APK in the project/app/build/ folder:

BEFORE gradle 3.1.0

applicationVariants.all { variant ->
    variant.outputs.all { output ->
        outputFileName = new File(
                output.outputFile.parent,
                output.outputFile.name)
    }
}

IN or AFTER gradle 3.1.0

applicationVariants.all { variant ->
    variant.outputs.all { output ->
        outputFileName = new File(
                "./../../../../../build/",
                output.outputFile.name)
    }
}
Jacinda answered 29/3, 2018 at 14:38 Comment(0)
W
16

I think using "./../../../" is bad solution... I use common gradle script for several projects and I want to make code to be independency from depth of output dir.

After some researching I found this solution for gradle plugin 3.1.2:

applicationVariants.all { variant ->
    variant.outputs.all { output ->
        def relativeRootDir = output.packageApplication.outputDirectory.toPath()
                 .relativize(rootDir.toPath()).toFile()
        output.outputFileName = new File( "$relativeRootDir/release", newOutputName)
    }
}
Weatherboard answered 14/6, 2018 at 16:32 Comment(1)
This does not work any more. This answer https://mcmap.net/q/113136/-android-studio-3-1-build-gradle-3-1-0-absolute-path-are-not-supported-when-setting-an-output-file-name is the simpler and working solution.Isauraisbel
I
15

The simplest solution for Android Gradle plugin 3.4.0+ is as below:

Assemble/concatenate your new file name:

def newFileName = "assemble-your-new-file-name"

Then, simply assign it back.

outputFileName = newFileName

More specifically is as following

android.applicationVariants.all { variant ->
    variant.outputs.each { output ->
        // Redirect your apks to new defined location to outputDirPath
        def outputDirPath = new File("${project.rootDir.absolutePath}/apks/${variant.flavorName}/${variant.buildType.name}")
        variant.packageApplicationProvider.get().outputDirectory = outputDirPath

        def apkFileName = "${rootProject.name}_${android.defaultConfig.versionName}.apk"
        output.outputFileName = apkFileName // directly assign the new name back to outputFileName
    }
}
Isauraisbel answered 15/4, 2019 at 2:51 Comment(6)
What's the best way to get the output apk file name/path as opposed to the output directory?Sarge
@DavidBerry, output.outputFileName is the apk file name. But, i am not sure this is the best way or not.Isauraisbel
at least on 5.1.1 outputFileName gives an unknown property error.Sarge
@DavidBerry, outputFileName is a Android Gradle plug-in property, not a Gradle build-in property. Currently, the plugin version is 3.4.2, and its corresponding Gradle version is 5.+. At least for me, this tool set works well.Isauraisbel
See https://mcmap.net/q/46221/-what-is-the-real-android-studio-gradle-version for more about the versionIsauraisbel
Thanks ${rootProject.name} this is what I am looking forKondon
O
9

I experienced the same issue. I haven't put the effort in to figure out exactly what's happened but there's a simple fix.

Just remove the root from your new file and trust the framework, i.e. change your code to

outputFileName = new File("release", releaseFileName.toLowerCase())

That was sufficient for us. We don't care about where the apk goes, only the name of the apk for a particular flavour.

Oneiric answered 28/3, 2018 at 10:7 Comment(2)
I need to put output apk (app-release.apk) in specific path in project. In folder MyProject/release/app-relese.apk. How I can do this?Tumulus
Sorry, I don't have enough depth here. I'd need to set up gradle debugging and/or get into the sources to figure this out. My guess is there's some way to convert your path to a path relative to the project root. Quite why this change has been enforced and seemingly undocumented I don't know. Looks like you have a workaround for yourself at least :)Oneiric
T
2

I found solution:

def releaseFileName = "${rootProject.name}_${defaultConfig.versionName}.apk"
outputFileName = "/../../../../../release/" + releaseFileName.toLowerCase()

And now output file app-release.apk success created in MyProject/release/app-relese.apk

Tumulus answered 28/3, 2018 at 12:59 Comment(0)
B
1

Use variant.packageApplicationProvider.get().outputDirectory to avoid warning "variantOutput.getPackageApplication() is obsolete"

applicationVariants.all { variant ->
    variant.outputs.each { output ->
        variant.packageApplicationProvider.get().outputDirectory = new File(
            project.rootDir.absolutePath + "/release")

        def releaseFileName = "${rootProject.name}_${defaultConfig.versionName}.apk"
        output.outputFileName = releaseFileName.toLowerCase()
    }
}
Babirusa answered 9/4, 2019 at 16:59 Comment(0)
F
1

For gradle-6.5.1:

applicationVariants.all { variant ->
          variant.outputs.all { output ->
                  outputFileName = new File("ApkName.apk")
          }
 }
Firecrest answered 22/12, 2020 at 12:19 Comment(0)
H
1

I just upgraded our project to Gradle 7.6 from 4.1.2, which removed the ability to set outputFileName to a relative dir.

This code below worked for me. It copies the build output from the expected directories to the directory of your choice. In my case, this was 2 levels up (../../.).

The key to this working is binding the copy task to the assemble tasks completion, with finalizedBy so it only runs after the Apk's have been created.

android.applicationVariants.all { variant ->
    variant.outputs.all { output ->
        File outDir = file("${project.buildDir}/outputs/apk")
        File apkDir = file("${project.buildDir}/outputs/apk/${variant.flavorName}/${variant.buildType.name}")

        def task = project.tasks.create("publish${variant.name.capitalize()}Apk", Copy)
        task.from apkDir
        task.into outDir
        task.include "**/*"
        task.doLast {
            println ">>>publish ${variant.name} success!" +
                    "\nfrom: ${apkDir}" +
                    "\ninto: ${outDir}"
        }
        output.assemble.finalizedBy task
    }
}
Hosmer answered 15/3, 2023 at 21:56 Comment(0)
K
0

If you want to append the version name and version code do it like:

applicationVariants.all { variant ->
        variant.outputs.all {
            def versionName = variant.versionName
            def versionCode = variant.versionCode
            def variantName = variant.name
            outputFileName = "${rootProject.name}" + '_' + variantName + '_' + versionName + '_' + versionCode + '.apk'
        }
    }
Kondon answered 5/11, 2020 at 5:38 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.