Editing AndroidManifest.xml in Gradle task processManifest.doLast has no effect when running app from Android Studio

本秂侑毒 提交于 2019-12-05 08:11:47

I figured out that it's related to the Instant Run feature introduced in Android Studio 2.0. If I turn it off, everything works as expected. But since I want to use Instant Run, I digged a little further.

The thing is, with Instant Run enabled the intermediate AndroidManifest.xml file will be at another location, namely /build/intermediates/bundles/myflavor/instant-run/. That means I was effectively editing the wrong file. That other manifest file is accessible with the property instantRunManifestOutputFile, which can be used instead of manifestOutputFile.

To make it work in all use-cases I check both temporary manifest files whether they exist and modify them if so:

applicationVariants.all { variant ->
    variant.outputs.each { output ->
        output.processManifest.doLast {
            [output.processManifest.manifestOutputFile,
             output.processManifest.instantRunManifestOutputFile
            ].forEach({ File manifestOutFile ->
                if (manifestOutFile.exists()) {
                    def newFileContents = manifestOutFile.getText('UTF-8').replace("</application>", "<meta-data ... /></application>")
                    manifestOutFile.write(newFileContents, 'UTF-8')
                }
            })
        }
    }
}

There is literally no documentation of instantRunManifestOutputFile. The only Google search result I got was the Android Gradle Plugin source code. But then I also found a third potential manifest file property aaptFriendlyManifestOutputFile, which I don't know what it's about either...

I want to add some additional information to this question. The answer from @Floern is a bit outdated. The code is working on old Gradle versions. The new version of Gradle says that manifestOutputFile is deprecated and will be removed soon. instantRunManifestOutputFile doesn't exists at all. So, here is the example for the new Gradle version:

applicationVariants.all { variant ->                
    variant.outputs.each { output ->
        output.processManifest.doLast {
            def outputDirectory = output.processManifest.manifestOutputDirectory                
            File manifestOutFile = file(new File(outputDirectory, 'AndroidManifest.xml'))
            if(manifestOutFile.exists()){

                // DO WHATEVER YOU WANT WITH MANIFEST FILE. 

            }
        }
    }
}

Hope this will help someone.

there are difference with various gradle version, for me, I Used gradle-5.5-rc-3 and com.android.tools.build:gradle:3.4.1 so this would work :

def static setVersions(android, project, channelId) {
    android.applicationVariants.all { variant ->
        variant.outputs.each { output ->
            def processorTask = output.processManifestProvider.getOrNull()
            processorTask.doLast { task ->
                def directory = task.getBundleManifestOutputDirectory()
                def srcManifestFile = "$directory/AndroidManifest.xml"
                def manifestContent = new File(srcManifestFile).getText()
                def xml = new XmlParser(false, false).parseText(manifestContent)

                xml.application[0].appendNode("meta-data", ['android:name': 'channelId', 'android:value': '\\' + channelId])

                def serializeContent = groovy.xml.XmlUtil.serialize(xml)
                def buildType = getPluginBuildType(project)
                new File("${project.buildDir}/intermediates/merged_manifests/$buildType/AndroidManifest.xml").write(serializeContent)
            }
        }
    }
}

def static getPluginBuildType(project) {
    def runTasks = project.getGradle().startParameter.taskNames
    if (runTasks.toString().contains("Release")) {
        return "release"
    } else if (runTasks.toString().contains("Debug")) {
        return "debug"
    } else {
        return ""
    }
}

the location of intermediates/merged_manifests was found from module's build directory, it could be others depends on android-plugin version, just look into the build directory and find yours.

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!