从 Android Studio 运行应用程序时,在 Gradle 任务 processManifest.doLast 中编辑 AndroidManifest.xml 无效

2023-12-22

我使用以下 Gradle 脚本在编译时对 AndroidManifest.xml 进行一些修改。在这个例子中我想注入一个<meta-data>元素。该代码基于这个答案 https://stackoverflow.com/a/27372806/559745.

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

当我在 Android Studio 中执行 Gradle 同步或从命令行进行干净构建时,这会按预期工作:可以从应用程序内访问元数据。

但是当我从 Android Studio 运行应用程序时,修改后的清单似乎被忽略,因为插入的元数据不是 APK 中编译清单的一部分,并且应用程序本身也无法在运行时找到它,元数据根本不存在。

在所有情况下,合并的中间 AndroidManifest.xml(在/构建/中间体/清单/)确实包含更改,但由于某种原因,如果我运行该应用程序,它看起来会被忽略。

为了使其更加明显,我尝试插入一些无效的 XML:在这种情况下,Gradle 同步和干净构建按预期失败,因为清单中存在语法错误。但我仍然能够从 Android Studio 运行该应用程序,因此修改实际上被忽略了。

重现此问题的最简单方法是首先清理项目(在 Android Studio 中),这会导致重新处理清单(如果出现语法错误,我会按预期失败),然后运行应用程序,即使使用无效的清单。

请注意,任务在doLast每次执行:Aprintln()打印任务中的内容,并且中间清单包含更改。

就好像在执行我的任务之前清单已编译到 APK 中一样。

这里的问题出在哪里呢?

我正在使用 Android Studio 2.0 和 Android Gradle 插件 2.0.0。


我发现这与Android Studio 2.0中引入的Instant Run功能有关。如果我将其关闭,一切都会按预期进行。但由于我想使用 Instant Run,所以我进一步挖掘了一些。

问题是,启用即时运行后,中间 AndroidManifest.xml 文件将位于另一个位置,即/build/intermediates/bundles/myflavor/instant-run/。这意味着我实际上编辑了错误的文件。其他清单文件可以通过属性访问instantRunManifestOutputFile,可以用来代替manifestOutputFile.

为了使其在所有用例中都能工作,我检查两个临时清单文件是否存在,如果存在则修改它们:

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')
                }
            })
        }
    }
}

实际上没有任何文档instantRunManifestOutputFile。我得到的唯一 Google 搜索结果是 Android Gradle Plugin 源代码。但后来我还发现了第三个潜在的清单文件属性aaptFriendlyManifestOutputFile,我也不知道它是关于什么的......

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

从 Android Studio 运行应用程序时,在 Gradle 任务 processManifest.doLast 中编辑 AndroidManifest.xml 无效 的相关文章