40

I am using the following simplified configuration in an Android application project.

android {
    compileSdkVersion 20
    buildToolsVersion "20.0.0"

    defaultConfig {
        minSdkVersion 8
        targetSdkVersion 20
        versionCode 1
        versionName "1.0.0"

        applicationVariants.all { variant ->
            def file = variant.outputFile
            def fileName = file.name.replace(".apk", "-" + versionName + ".apk")
            variant.outputFile = new File(file.parent, fileName)
        }
    }    
}

Now that I updated the Gradle plug-in to v.0.13.0 and Gradle to v.2.1. the following warnings appear:

WARNING [Project: :MyApp] variant.getOutputFile() is deprecated. 
    Call it on one of variant.getOutputs() instead.
WARNING [Project: :MyApp] variant.setOutputFile() is deprecated. 
    Call it on one of variant.getOutputs() instead.
WARNING [Project: :MyApp] variant.getOutputFile() is deprecated. 
    Call it on one of variant.getOutputs() instead.
WARNING [Project: :MyApp] variant.setOutputFile() is deprecated. 
    Call it on one of variant.getOutputs() instead. 

How can I rewrite the Groovy script to get rid of the deprecation warnings?

JJD
  • 50,076
  • 60
  • 203
  • 339

4 Answers4

64

Building on the answer from Larry Schiefer you can change the script to something like this:

android {
    applicationVariants.all { variant ->
        variant.outputs.each { output ->
            def outputFile = output.outputFile
            if (outputFile != null && outputFile.name.endsWith('.apk')) {
                def fileName = outputFile.name.replace('.apk', "-${versionName}.apk")
                output.outputFile = new File(outputFile.parent, fileName)
            }
        }
    }
}
Community
  • 1
  • 1
Thorbear
  • 2,303
  • 28
  • 23
  • Have you actually tried running this code? I get `Could not find property 'file' on com.android.build.gradle.internal.api.ApplicationVariantImpl_Decorated@4b50996.` This android gradle plugin is brutal. – Merk Oct 11 '14 at 00:30
  • @Merk Actually, yes, I came here looking for an answer to the same question, and finally managed to get it working with the snippet above (although I've got some slightly different code inside the if). Sounds like you've written something wrong if you cannot find the property 'file', since no such property is used in my snippet :) – Thorbear Oct 11 '14 at 00:35
  • Puzzling because this is the offending line: `output.outputFile = new File(file.parent, "AppName_playstorebuild.apk")`. BTW I am using `classpath 'com.android.tools.build:gradle:0.13.0'` – Merk Oct 11 '14 at 02:02
  • @Merk And did you include the two lines before it? Without `def file = output.outputFile` the property 'file' will obviously not exist. – Thorbear Oct 11 '14 at 12:48
  • From my testing, `output.outputFile = new File(outputFile.parent, fileName)` appears to still cause this warning to be thrown. Started a separate question thread [here](http://stackoverflow.com/questions/26688660/variant-getoutputfile-is-deprecated-call-it-on-one-of-variant-getoutputs-in) – Zac Sweers Nov 01 '14 at 11:08
  • I'm having an error. Apk's name and what Android Studio is looking for in the local path isn't the same. I've posted something similar here: http://stackoverflow.com/questions/30082087/gradle-autoincrement-and-rename-apk-i-o-error – hadez30 May 07 '15 at 02:31
  • 1
    I am getting this error on M1 MBP: `java.lang.RuntimeException: com.android.build.gradle.internal.crash.ExternalApiUsageException: groovy.lang.GroovyRuntimeException: Cannot set the value of read-only property 'outputFile'`. Target API 30, Gradle plugin 4.2.2 Gradle versin 6.9. – Olcay Ertaş Dec 20 '21 at 07:30
16

The complete code snippet looks like that one:

// Customize generated apk's name with version number
applicationVariants.all { variant ->
    variant.outputs.each { output ->
        def outputFile = output.outputFile
        if (outputFile != null && outputFile.name.endsWith('.apk')) {
            def manifestParser = new com.android.builder.core.DefaultManifestParser()
            def fileName = outputFile.name.replace(".apk", "-DEBUG-" + manifestParser.getVersionName(android.sourceSets.main.manifest.srcFile) + ".apk")
            output.outputFile = new File(outputFile.parent, fileName)
        }
    }
}
JJD
  • 50,076
  • 60
  • 203
  • 339
Thomas
  • 161
  • 3
11

The build variant output API has changed in the latest Android Gradle plugin. It now allows multiple output files (or directories), which is why this method has been marked as deprecated. If you use variant.outputs instead, it will give you a Collection you can then iterate over and get each output file. You'll have to verify the file object is non-null and that it matches your criteria (e.g. has a '.apk' extension.) Then you can create a new File object and add it to the output within the collection.

Larry Schiefer
  • 15,687
  • 2
  • 27
  • 33
  • Neither `variant.outputs.outputFile.name = "NewBuildName.apk"` nor `variant.outputs.add(new File("NewBuildName.apk"))` has any effect, so I'm not sure what action you're suggesting. – Merk Oct 09 '14 at 16:56
  • 6
    Where is the documentation to see what properties are in the "output" object? – whizzle Nov 05 '14 at 22:08
  • 4
    Unfortunately, at this point in time this is largely undocumented. You have to rely on in-line help within Android Studio (not very useful) or go digging through Groovy/Java code within the plugin itself to find the details. Since `outputs` is a `Collection` you should be able to find docs on the Groovy/Java `Collection` object. – Larry Schiefer Nov 06 '14 at 00:30
4

Android Plugin for Gradle 3.0.0

You can use like this

android.applicationVariants.all { variant ->
    variant.outputs.all {
        outputFileName = "${variant.name}-${variant.versionName}.apk"
    }
}

you can get more on the features and new changes in android documentation https://developer.android.com/studio/build/gradle-plugin-3-0-0-migration.html#update_gradle

inder
  • 303
  • 2
  • 12