Android Gradle Plug 4.1.0 升级后gradle获取manifest位置失败问题解决

 更新时间:2020-10-18 11:15:10   作者:佚名   我要评论(0)

问题背景
项目编译过程中,使用了类似Android Gradle Plugin的gradle插件进行编译,在最终打包apk时,会动态修改manifest文件。
近期发现线上用户有反应升级到以下开

问题背景

项目编译过程中,使用了类似Android Gradle Plugin的gradle插件进行编译,在最终打包apk时,会动态修改manifest文件。

近期发现线上用户有反应升级到以下开发环境后,打包apk后manifest文件中没有应有的任何配置。

Android Gradle Plugin:4.1.0
Gradle:6.5
Android Studio:4.1

确认调查方向

首先要确认清楚到底是上述3个哪个的升级导致的问题。

在本地进行环境升级过程验证了以下结论:

Android Gradle Plugin:4.1.0 强制要求 Android Studio:4.1 + Gradle:6.5。然而 以下环境下打包过程是正常的:

Android Gradle Plugin:4.0.2
Gradle:6.5
Android Studio:4.1

Android Gradle Plugin:4.0.2 是 4.1 的前一个版本,至此可以确认是 Android Gradle Plugin:4.1.0 的升级导致的不兼容问题。

明确了调查的方向,接下来就可以有的放矢了。

调查分析

我们的gradle插件,是通过以下代码获取到manifest文件后做处理的:

new File(output.processManifestProvider.get().manifestOutputDirectory.get().getAsFile(), "AndroidManifest.xml")

其实并非如此简单,只是这一句是最关键的。在gradle插件中增加了一些关键打印语句后,编译过程中得到了以下错误提示:

Could not get unknown property 'manifestOutputDirectory' for task ':app:processDebugManifest' of type com.android.build.gradle.tasks.ProcessMultiApkApplicationManifest

百度了一下,没有任何相关记录,毕竟距离 Android Gradle Plugin:4.1.0 正式发布才过去2个月,只好自给自足。

很明显是读取manifest文件位置的属性失效了,那最直接的方法就是看源码。找到 Android Gradle Plugin:4.1.0 的jar包看看就行。

又是百度一下,很可惜,没有下载地址。

上JCenter找,结果JCenter仓库只更新到2.x版本。

也对,好像是从 Android Studio 3.0 开始,google就将 Android Gradle Plugin 转移至 google() 仓库了,那只能去 google() 仓库找了,一时半会也不知道具体地址,以前的编译过程中也没留意看studio的编译日志输出,当然如果是一个全新工程环境,编译一下,肯定能找到仓库地址的,不过我懒得搞。

先到AS的缓存路径下碰碰运气吧,不过碰运气也得先有个方向,别忘了Android Gradle Plugin的classpath配置:

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

果不其然,在以下路径找到了:

/Users/jackie/.gradle/caches/modules-2/files-2.1/com.android.tools.build/gradle

加载过的各种版本都有,直接拿到 4.1.0 的jar包看源码,在 ProcessMultiApkApplicationManifest.class 中找到了以下代码:

File mergedManifestOutputFile = new File(((Directory)getMultiApkManifestOutputDirectory().get()).getAsFile(), 
  FileUtils.join(new String[] { dirName, 
    "AndroidManifest.xml" }));

同时还有一个抽象方法:

public abstract DirectoryProperty getMultiApkManifestOutputDirectory();

看来属性已经变成了 multiApkManifestOutputDirectory。

如果不确定,我们再看看 4.0.2 的源码,在 ProcessApplicationManifest.class 中找到了以下代码:

复制代码 代码如下:
File manifestOutputFile = new File(((Directory)getManifestOutputDirectory().get()).getAsFile(), FileUtils.join(new String[] { apkData.getDirName(), "AndroidManifest.xml" }));

很明显,在 4.0.2 版本时,获取manifest文件路径的属性确实是 manifestOutputDirectory ,而task本质上是一个 ProcessApplicationManifest 实例,但从 4.1.0 版本开始, task变为 ProcessMultiApkApplicationManifest 的实例,属性变为 multiApkMnifestOutputDirectory 了。

好了,剩下的就是做一下版本兼容了,大功告成。

复制代码 代码如下:
new File(output.processManifestProvider.get().multiApkManifestOutputDirectory.get().getAsFile(), "AndroidManifest.xml")

总结

大部分基于gradle的编译脚本,其工作原理都一样,就是在编写自定义的task、在某个预设的task之前或之后做自定义的特殊处理等等,更高级一点的gradle插件也不例外。

而 Android Gradle Plugin 同样也只是一个Google官方开发的gradle插件,每次升级版本都会伴随着一些“task名变更”、“task处理内容变更”、“task执行顺序变更”等等的更新,这些更新很可能就会影响到我们这些基于其“预置task”做特殊处理的gradle插件,所以大部分版本兼容问题都应该从这个方向出发调查。

另外,有时候Gradle的升级也会带来一些兼容问题。

到此这篇关于Android Gradle Plug 4.1.0 升级后gradle获取manifest位置失败问题解决的文章就介绍到这了,更多相关Android Gradle4.1升级内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

您可能感兴趣的文章:
  • AndroidStudio升级4.1坑(无法启动、插件plugin不好用、代码不高亮)
  • Android studio升级4.1时遇到的问题记录
  • Android Studio IDE升级4.1以后Start Failed
  • Android将Xamarin For VS升级为4.1.0.530版教程

相关文章

  • Android Gradle Plug 4.1.0 升级后gradle获取manifest位置失败问题解决

    Android Gradle Plug 4.1.0 升级后gradle获取manifest位置失败问题解决

    问题背景 项目编译过程中,使用了类似Android Gradle Plugin的gradle插件进行编译,在最终打包apk时,会动态修改manifest文件。 近期发现线上用户有反应升级到以下开
    2020-10-18
  • AndroidStudio升级4.1后启动失败Plugin问题解决

    AndroidStudio升级4.1后启动失败Plugin问题解决

    AS升级4.1 后启动失败 Plugin问题 start fail 弹窗如下: Internal error. Please refer to https://code.google.com/p/android/issues java.lang.NoSuchMethodErr
    2020-10-18
  • Java中方法使用的深入讲解

    Java中方法使用的深入讲解

    方法的使用 1.方法的基本用法 什么是方法,方法就是一个代码片段,类似于C/C++ 语言中的"函数"。 1.1方法存在的意义: 是能够模块化的组织代码(当代码规模比较复
    2020-10-18
  • js中复选框的取值及赋值示例详解

    js中复选框的取值及赋值示例详解

    1、复选框的取值:(js部分) var checkboxdata = $(“input[name=payoperator]:checked”).map(function() { return $(this).val(); }).get().join(",");
    2020-10-18
  • 详解如何在Javascript中使用Object.freeze()

    详解如何在Javascript中使用Object.freeze()

    Object.freeze() Object.freeze() 方法可以冻结一个对象。一个被冻结的对象再也不能被修改;冻结了一个对象则不能向这个对象添加新的属性,不能删除已有属性,不
    2020-10-18
  • Android Studio升级到4.1以后插件问题解决

    Android Studio升级到4.1以后插件问题解决

    当把Android Studio升级到4.1以后插件提示不可用,然后启动的报下面的错: 错误的意思是该插件只支持IDEA,然后想把这个插件删除,发现在已安装的插件中是找
    2020-10-18
  • 如何利用python读取micaps文件详解

    如何利用python读取micaps文件详解

    最近用编程处理文件挺多的,matlab用得比较熟,但还是想用python来写写,Fortran就不用了。 所用到的数据如下图,前面4行是说明,实际要用的数据是第5行开始。 一共
    2020-10-18
  • Python如何使用vars返回对象的属性列表

    Python如何使用vars返回对象的属性列表

    英文文档: vars([object]) Return the __dict__ attribute for a module, class, instance, or any other object with a __dict__ attribute. Objects such
    2020-10-17
  • Servlet机制Pushlet原理及用法详解

    Servlet机制Pushlet原理及用法详解

    Pushlet(一种comet 架构的实现)是基于Servlet 机制,数据从server端的Java 对象直接推送(push)到客户端浏览器的(动态)HTML 页面,而无需任何Java applet 或者
    2020-10-17
  • Nodejs在局域网配置https访问的实现方法

    Nodejs在局域网配置https访问的实现方法

    零、需求: 做一个局域网WebRTC视频聊天系统,需要用到HTTPS。因此,配置Node.js使其支持HTTPS访问。 一、解决 在线生成和证书 访问:https://csr.chinassl.net/g
    2020-10-17

最新评论