variantOutput.getPackageApplication() is obsolete
Asked Answered
P

10

33

with Gradle 4.10.1 and the Android Gradle plugin updated to 3.3.0, I get the following warning:

WARNING: API 'variantOutput.getPackageApplication()' is obsolete and has been replaced with 'variant.getPackageApplicationProvider()'.

the line, with the surrounding context (which is assigning output file-names by build variant):

applicationVariants.all { variant ->
    variant.outputs.all { output ->

        if (variant.getBuildType().getName() in rootProject.archiveBuildTypes) {

            def buildType = variant.getBuildType().getName()
            if (variant.versionName != null) {

                def baseName = output.baseName.toLowerCase()
                String fileName = "${rootProject.name}_${variant.versionName}-${baseName}.apk"

                // this is the line:
                outputFileName = new File(output.outputFile.parent, fileName).getName()
            }
        }
    }
}

the migration guide isn't too helpful; while the variant.outputs.all might be at fault - just have no clue with what to replace that - and the migration guide refers to tasks and not to build variants. when disabling File → Settings → Experimental → Gradle → Only sync the active variant, I get even more deprecation warnings (the point is, that none of these methods are being called directly):

WARNING: API 'variant.getAssemble()' is obsolete and has been replaced with 'variant.getAssembleProvider()'.
WARNING: API 'variantOutput.getProcessResources()' is obsolete and has been replaced with 'variantOutput.getProcessResourcesProvider()'.
WARNING: API 'variantOutput.getProcessManifest()' is obsolete and has been replaced with 'variantOutput.getProcessManifestProvider()'.
WARNING: API 'variant.getMergeResources()' is obsolete and has been replaced with 'variant.getMergeResourcesProvider()'.
WARNING: API 'variant.getMergeAssets()' is obsolete and has been replaced with 'variant.getMergeAssetsProvider()'.
WARNING: API 'variant.getPackageApplication()' is obsolete and has been replaced with 'variant.getPackageApplicationProvider()'.
WARNING: API 'variant.getExternalNativeBuildTasks()' is obsolete and has been replaced with 'variant.getExternalNativeBuildProviders()'.
WARNING: API 'variantOutput.getPackageApplication()' is obsolete and has been replaced with 'variant.getPackageApplicationProvider()'.

Q: how can these deprecation warnings be avoided by migration to the new API?

Poler answered 15/1, 2019 at 21:13 Comment(10)
output.outputFile.parent => variant.getPackageApplicationProvider().get().outputs.files[1] .... google should fix it because the problem is output.outputFile it's internally calling getPackageApplication()Kelleykelli
@Kelleykelli this at least fixes the one warning; while then it complains: variant.getExternalNativeBuildTasks() is obsolete... which would need to be replaced with variant.getExternalNativeBuildProviders()Poler
hehe variant.getExternalNativeBuildProviders() this comes from .... let me guess ... io.fabric plugin ...Kelleykelli
@Kelleykelli you are correct; with debug enabled this hints for: com.crashlytics.tools.gradle.ProjectVariantState.resolveDebugNativeLibsPath(ProjectVariantState.groovy:130). add the comment as an answer and I'd accept it, because it answers the primary question.Poler
So ... it's all Google's fault ... same as registerResGeneratingTask is deprecated, use registerGeneratedResFolders(FileCollection) from com.google.gms.google-services ... I give up with this ... I spent 2 days analyzing those warningsKelleykelli
@Kelleykelli I got used to ignore this one warning. but when the warnings get too many, at some point it becomes unclear, within who's responsibility they would be.Poler
I'm not sure if it's a good answer variant.getPackageApplicationProvider().get().outputs.files[1] doesnt looks good ... also variant.getPackageApplicationProvider().get().outputs.files[0] points to build\intermediates\incremental\packageVariant1Varian2... ... what if Google change 0 with 1 in next release? ... there should be easy way to get path to apk from either assemble or package taskKelleykelli
once Gradle 5.x will become the default, a whole lot more will break. most workarounds might only be temporary solutions. just found out that android.enableSeparateAnnotationProcessing = true fixes one incremental annotation processor warning for Room.Poler
developer.android.com/studio/known-issues ... "tasks that involve accessing outputFile objects no longer work. That's because variant-specific tasks are no longer created during the configuration stage. This results in the plugin not knowing all of its outputs up front, but it also means faster configuration times."Poler
@Kelleykelli I've just found a workaround for the registerResGeneratingTask().Poler
P
15

variantOutput.getPackageApplication() is being caused by a changed variant API.

changing output.outputFile.parent to variant.getPackageApplicationProvider().get().outputs.files[1] is at least a temporary workaround.

source: @Selvin.


variant.getExternalNativeBuildTasks() is being caused by the io.fabric plugin.

the next version of the io.fabric plugin will use variant.getExternalNativeBuildProviders().

source: 116408637; the confirmation for a promised fix (1.28.1).


These are caused by com.google.gms.google-services:

  • registerResGeneratingTask is deprecated, use registerGeneratedResFolders(FileCollection)

  • 'variant.getMergeResources()' is obsolete and has been replaced with 'variant.getMergeResourcesProvider()'

This blog post explains how to get rid of the com.google.gms.google-services plugin altogether, by adding the XML resources, which that plugin generates, eg. from build/generated/res/google-services/debug/values/values.xml into the regular debug/values/values.xml.


The most easy and the least effort might be:

buildscript {
    repositories {
        google()
        maven { url "https://maven.fabric.io/public" }
    }
    dependencies {
        //noinspection GradleDependency
        classpath "com.android.tools.build:gradle:3.2.1"
        classpath "io.fabric.tools:gradle:1.28.1"
    }
}

For debug information: ./gradlew -Pandroid.debug.obsoleteApi=true mobile:assembleDebug

None of these warnings changes the behavior in any way.

Poler answered 17/1, 2019 at 23:55 Comment(5)
I guess it's related to their plugins, and we can not really do anything.Banwell
in my case it was dexcount gradle plugin. After I upgraded it to version 0.8.6 warning is gone.Chessa
@IlyaEremin there may be various plugins still using these methods.Poler
@@martim zeitler. I have the same issue but I'm not using fabric pluginAnklet
@Ggriffo then likely it's some other plugin using that deprecated API.Poler
Q
9

Update Fabric gradle plugin to 1.28.1

dependencies {
   classpath 'io.fabric.tools:gradle:1.28.1'
}

Changelog: https://docs.fabric.io/android/changelog.html#march-15-2019

Eliminated obsolete API warnings by switching to Gradle’s task configuration avoidance APIs, when available.

Quoth answered 20/3, 2019 at 21:5 Comment(0)
C
2

You could use the simpler one, similar to this example:

applicationVariants.all { variant ->
            variant.outputs.all { output ->
                outputFileName = "${globalScope.project.name}-${variant.versionName}_${output.baseName}.apk"
            }
        }

and the result would be my_app-1.9.8_flavor1-release.apk.

In your code the problematic part (that generate the warning) is output.outputFile:

..
outputFileName = new File(output.outputFile.parent, fileName).getName()
..
Coax answered 29/4, 2019 at 22:51 Comment(0)
L
2

The problem is that output.outputFile is internally calling getPackageApplication()

I solved this problem by setting the directory and name of the output file myself.

applicationVariants.all { variant ->
    variant.outputs.each { output ->
        def outputDir = new File("${project.buildDir.absolutePath}/outputs/apk/${variant.flavorName}/${variant.buildType.name}")
        def outputFileName = "app-${variant.flavorName}-${variant.buildType.name}.apk"
        // def outputFile = new File("$outputDir/$outputFileName")

        variant.packageApplicationProvider.get().outputDirectory = new File("$outputDir")
        output.outputFileName = outputFileName
    }
}
Ly answered 16/5, 2019 at 8:22 Comment(0)
M
2

So I was getting the same issue (as of this date, running Gradle 5.4.1). Furthermore, I didn't see an answer that effectively covered both application projects as well as library projects.

Thus, I wanted to make something that could theoretically be used on any project to make a single build.gradle for the whole project, if desired. Because it turned out quite well, I figured I'd add it in case someone wants something that will work for both application and library projects.

Edit:

I have updated/optimized this method since originally posting it. I am now using gradle 6.3 with Kotlin DSL and the following works swimmingly.

Edit2:

It seems somewhere in Android Gradle build tools 4.1.0 (beta) that they disabled build config generation for library projects by default, so I had to change one line to accept a null value with a backup, updated below.

/**
 * Configures the output file names for all outputs of the provided variant. That is, for
 * the provided application or library.
 *
 * @param variant Passed in with {android.defaultConfig.applicationVariants.all.this}
 * @param project The project from which to grab the filename. Tip: Use rootProject
 * @param formatString Format string for the filename, which will be called with three 
 * arguments: (1) Project Name, (2) Version Name, (3) Build Type. ".apk" or ".aar" is 
 * automatically appended. If not provided, defaults to "%1$s-%2$s_%3$s"
 */
@SuppressWarnings("UnnecessaryQualifiedReference")
fun configureOutputFileName(
    variant: com.android.build.gradle.api.BaseVariant,
    project: Project,
    formatString: String = "%1\$s-%2\$s_%3\$s"
) {
    variant.outputs.configureEach {
        val fileName = formatString.format(project.name,
            outputVariant.generateBuildConfigProvider.orNull?.versionName?.orNull ?:
                project.version, variant.buildType.name)
        val tmpOutputFile: File = when (variant) {
            is com.android.build.gradle.api.ApplicationVariant -> 
                File(variant.packageApplicationProvider!!.get().outputDirectory.asFile
                    .get().absolutePath,"$fileName.apk")
            is com.android.build.gradle.api.LibraryVariant -> 
                File(variant.packageLibraryProvider!!.get().destinationDirectory.asFile
                    .get().absolutePath,"$fileName.aar")
            else -> outputFile
        }
        (this as com.android.build.gradle.internal.api.BaseVariantOutputImpl)
            .outputFileName = tmpOutputFile.name
        println("Output file set to \"${tmpOutputFile.canonicalPath}\"")
    }
}

Original:

The relevant part is here.

android {
    if (it instanceof com.android.build.gradle.AppExtension) {
        it.applicationVariants.all { 
            com.android.build.gradle.api.ApplicationVariant variant ->
                configureOutputFileName(variant, project)
        }
    } else if (it instanceof com.android.build.gradle.LibraryExtension) {
        it.libraryVariants.all { com.android.build.gradle.api.LibraryVariant variant ->
            configureOutputFileName(variant, project)
        }
    }
}

Which simply calls the method below.

@SuppressWarnings("UnnecessaryQualifiedReference")
private void configureOutputFileName(com.android.build.gradle.api.BaseVariant variant,
    Project project) {
    variant.outputs.all { output ->
        def buildType = variant.buildType.name
        String tmpOutputFileName = outputFileName
        if (variant instanceof com.android.build.gradle.api.ApplicationVariant) {
            String fileName = "${project.name}-${variant.versionName}_${buildType}.apk"
            def defaultOutputDir = variant.packageApplicationProvider.get().outputDirectory
            tmpOutputFileName = new File(defaultOutputDir.absolutePath, fileName).name
        }
        if (variant instanceof com.android.build.gradle.api.LibraryVariant) {
            String fileName = "${project.name}_${buildType}.aar"
            def defaultOutputDir = variant.packageLibraryProvider.get()
                .destinationDirectory.asFile.get()
            tmpOutputFileName = new File(defaultOutputDir.absolutePath, fileName).name
        }
        println(tmpOutputFileName)
        outputFileName = tmpOutputFileName
    }
}
Martynne answered 19/6, 2019 at 21:41 Comment(0)
F
1

I wasn't using output.outputFile.parentin my gradle. The cause for variantOutput.getPackageApplication() obsolete warning was the dex count plugin. I updated it to 0.8.6 and warning is gone.

'com.getkeepsafe.dexcount:dexcount-gradle-plugin:0.8.6'
Forehanded answered 5/7, 2019 at 5:58 Comment(0)
N
0

The culprit of below warning is output.outputFile

WARNING: API 'variantOutput.getPackageApplication()' is obsolete and has been replaced with 'variant.getPackageApplicationProvider()'.

To get rid of this warning for Android Gradle plugin 3.4.0+, you can manually assemble the output path as below:

def selfAssembledOutputPath = new File("${project.buildDir.absolutePath}/outputs/apk/${variant.flavorName}/${variant.buildType.name}")

Then replace your below line with selfAssembledOutputPath defined above

// this is the line:
outputFileName = selfAssembledOutputPath
Nasho answered 31/7, 2019 at 2:11 Comment(0)
S
0

A bit less dodgy solution:

def variant = findYourVariantSomehow()
def output = findCorrectOutputInVariant(variant)
def fileName = output.outputFileName

def fileDir = variant.packageApplicationProvider.get().outputDirectory.get()

def apkFile = file("$fileDir/$fileName")

source

Surfacetoair answered 10/4, 2020 at 14:35 Comment(0)
W
-1

I used to wirite like this:

android.applicationVariants.all { variant ->
    if ("release" == variant.buildType.name) {
        variant.outputs.all { output ->
            outputFileName = output.outputFile.name.replace("-release", "")
        }
        variant.assemble.doLast {
            variant.outputs.all { output ->
                delete output.outputFile.parent + "/output.json"
                copy {
                    from output.outputFile.parent
                    into output.outputFile.parentFile.parent
                }
                delete output.outputFile.parent
            }
        }
    }
}

The warning pop up each time, like open AS,sync,clean...

Then I found a way to write , it will just appear in build but will not pop up each time.

android.applicationVariants.all { variant ->
    if ("release" == variant.buildType.name) {
        assembleRelease.doLast {
            variant.outputs.all { output ->
                delete output.outputFile.parent + "/output.json"
                copy {
                    from output.outputFile.parent
                    into output.outputFile.parentFile.parent
                    rename { filename ->
                        filename.replace("-release", "")
                    }
                }
                delete output.outputFile.parent
            }
        }
    }
}

If you just don't want the warning pop each time, these may have some tips for you.

Whall answered 28/2, 2019 at 8:35 Comment(0)
C
-1

You can also use an older version of gradle. I changed my gradle version from 3.5.0 to 3.2.1 and it worked.enter image description here

Credent answered 20/9, 2019 at 20:17 Comment(1)
This merely depends on the Gradle version. Meanwhile have it working with little warnings, with the latest Fabric & Google Play Services plug-ins.Poler

© 2022 - 2024 — McMap. All rights reserved.