Gradle与插件的升级-3.5排坑之旅
2020年来了,一年一度的升级活动又要如期展开了,项目里面的老东西也该改进改进了。随着项目越来越大,编译时间成为了我们的瓶颈,虽然改变工程结构等方式能够提升编译速度,但是升级Gradle其实是不二法门。
目前项目的状态:
android studio : 3.4.2
gradle : 4.10.1
gradle插件:3.3.1
首次执行编译时间(执行命令-> ./gradlew assembleDebug):9m 17s
第二次执行编译时间: 6m 18s
以下是来自官网的数据:
插件版本 所需的 Gradle 版本
1.0.0 - 1.1.3 2.2.1 - 2.3
1.2.0 - 1.3.1 2.2.1 - 2.9
1.5.0 2.2.1 - 2.13
2.0.0 - 2.1.2 2.10 - 2.13
2.1.3 - 2.2.3 2.14.1+
2.3.0+ 3.3+
3.0.0+ 4.1+
3.1.0+ 4.4+
3.2.0 - 3.2.1 4.6+
3.3.0 - 3.3.2 4.10.1+
3.4.0 - 3.4.1 5.1.1+
3.5.0+ 5.4.1-5.6.4
预计更新为:
android studio : 3.5.0(必须)
gradle : 5.4.1
gradle插件:3.5.3
SDK Build Tools: 28.0.3 +
优点:
代码缩减(即摇树优化):从应用及其库依赖项中检测并安全地移除未使用的类、字段、方法和属性(这使其成为了一个对于规避 64k 引用限制非常有用的工具)。例如,如果您仅使用某个库依赖项的少数几个 API,缩减功能可以识别应用“未”使用的库代码并仅从应用中移除这部分代码。如需了解详情,请转到介绍如何缩减代码的部分。
资源缩减:从封装应用中移除不使用的资源,包括应用库依赖项中的不使用的资源。此功能可与代码缩减功能结合使用,这样一来,移除不使用的代码后,也可以安全地移除不再引用的所有资源。如需了解详情,请转到介绍如何缩减资源的部分。
混淆处理:缩短类和成员的名称,从而减小 DEX 文件的大小。如需了解详情,请转到介绍如何对代码进行混淆处理的部分。
优化:检查并重写代码,以进一步减小应用的 DEX 文件的大小。例如,如果 R8 检测到从未采用过给定 if/else 语句的 else {} 分支,则会移除 else {} 分支的代码。如需了解详情,请转到介绍代码优化的部分。
默认情况下,在构建应用的发布版本时,R8 会自动执行上述编译时任务。不过,您也可以停用某些任务或通过 ProGuard 规则文件自定义 R8 的行为。 事实上,R8 支持所有现有 ProGuard 规则文件,因此您在更新 Android Gradle 插件以使用 R8 时,无需更改现有规则。
#影响范围
根据下文的初步调研,这里给出影响范围,以备参考:
##整体升级计划
升级 | 具体内容 | 升级收益 | 是否影响到安居客 |
---|---|---|---|
Android Studio | 升级到3.5 | 系统运行状况、功能完善和错误修复,参考《Android Studio升级表》 | 是,需要同步升级 |
Gradle | 升级5.4.1 | 优化语法,使用R8提升编译速度,参考《Gradle升级表》 | 是,需要同步升级 |
Gradle 插件 | 升级3.5.3 | 同上,配套使用 | 是,需要同步升级 |
SDK Build Tools | 28.0.3 + | 同上,配套使用 | 是,需要同步升级 |
JDK | 1.8 | 同上,配套使用 | 是,需要同步升级 |
Kotlin Gradle 插件 | 1.3.40 | 同上,配套使用 | 是,需要同步升级 |
##Android Studio升级表
升级 | 具体内容 | 升级收益 | 备注 |
---|---|---|---|
增量注释 | 数据绑定注释处理器支持增量注释处理 | 提高了增量构建的性能 | 暂时用不到 |
单元测试 | 可缓存的单元测试 | 提效 | 暂时用不到 |
推荐内存设置 | 手动分配RAM上限 | 提高性能 | 开发者根据需要自己设置 |
内存使用情况报告 | 提交内存使用报告 | 供goolge完成内存分析 | 开发者根据需要自己设置 |
Windows:防病毒文件 I/O 优化 | 防病毒检测 | 防止病毒侵害 | 无win,不用 |
Apply Changes | 将代码和资源更改推送给正在运行的应用 | 无需重复构建 | 需要运行在Android 8.0及更高 |
Layout Editor | 对布局可视化、管理和互动功能 | ConstraintLayout构建布局时会更方便 | 升级即可使用 |
NDK 并排版本 | 同一计算机上可以使用不同版本的 NDK,甚至可以指定项目中每个模块应使用的 NDK 版本 | 并行构建 | 开发者可用 |
##Gradle升级表
升级 | 具体内容 | 升级收益 | 是否影响到安居客 |
---|---|---|---|
默认标签 | 不再需要enableFeaturePreview('IMPROVED_POM_SUPPORT')和enableFeaturePreview('STABLE_PUBLISHING')标志 | 自动配置 | 是,若有,则找到对应代码并删除 |
Java 9 & JAXB | 默认捆绑 | 自动配置 | 是,若有,则找到对应代码并删除 |
语法修改 | publishing {}不支持延时操作 | 使用afterEvaluate {} | 是,若有,则找到对应代码并删除 |
Java库分发插件 | 基于Java库插件而不是Java插件 | 使其行为略有不同 | 是,若有,则请确保在升级后检查内部版本是否符合预期 |
Java库分发插件 | 基于Java库插件而不是Java插件 | 使其行为略有不同 | 是,若有,则请确保在升级后检查内部版本是否符合预期 |
属性修改 | CheckstyleReport和FindBugsReport的html属性现在返回一个CustomizableHtmlReport实例 | 更易于从静态类型的语言(如Java和Kotlin)进行配置 | 是,若有,则请确保在升级后检查是否符合预期 |
语法修改 | <<对于任务定义不再有效 | 不能使用语法task myTask << { … } ,改用Task.doLast() | 是,若有,则需要修改 |
语法修改 | 域对象名称使用规范 | 不能使用 |
是,若有,则需要修改 |
语法修改 | -Dtest.single | 命令行删除,使用test filtering替代 | 是,若有,则需要修改 |
语法修改 | -Dtest.debug | 命令行删除,使用--debug-jvm替代 | 是,若有,则需要修改 |
语法修改 | -u / --no-search-upward | 命令行删除,使用settings.gradle文件 | 是,若有,则需要修改 |
语法修改 | --recompile-scripts | 命令行删除 | 是,若有,则需要修改 |
语法修改 | DirectoryBuildCache.setTargetSizeInMB(long)方法已被删除 | 改成DirectoryBuildCache.removeUnusedEntriesAfterDays | 是,若有,则需要修改 |
语法修改 | .org.gradle.readLoggingConfigFile系统属性不再执行任何操作 | 使用java.util.logging设置 | 是,若有,则需要修改 |
文件操作 | 不再可以使用as关键字或asType()方法将FileCollection对象转换为其他类型 | 无 | 是,若有,则需要修改 |
文件操作 | 不能再传递null作为CopySpec.from(Object,Action)的配置 | 无 | 是,若有,则需要修改 |
文件操作 | CopySpec.duplicatesStrategy不再可以为空 | 默认值的方法. 请改用DuplicatesStrategy.INHERIT | 是,若有,则需要修改 |
文件操作 | FileCollection.stopExecutionIfEmpty()方法已被删除 | 在FileCollection任务属性上使用@SkipWhenEmpty批注 | 是,若有,则需要修改 |
文件操作 | FileCollection.add()方法已删除 | 使用Project.files()和Project.fileTree()创建可配置的文件集合/文件树,并通过ConfigurableFileCollection.from()将其添加到它们 | 是,若有,则需要修改 |
文件操作 | SimpleFileCollection已被删除 | 改为使用Project.files(Object ...) | 是,若有,则需要修改 |
文件操作 | 无法扩展AbstractFileCollection改用Project.files()方法 | 改为使用getBuildDependencies()方法 | 是,若有,则需要修改 |
Java构建 | CompileOptions.bootClasspath属性已被删除 | 请改用CompileOptions.bootstrapClasspath | 是,若有,则需要修改 |
Java构建 | 无法将-source-path用作通用编译器参数 | CompileOptions.sourcepath | 是,若有,则需要修改 |
Java构建 | 无法将-processorpath用作通用编译器参数 | 应改用CompileOptions.annotationProcessorPath | 是,若有,则需要修改 |
Java构建 | 不再自动应用编译类路径上的注释处理器 | 应改用CompileOptions.annotationProcessorPath | 是,若有,则需要修改 |
Java构建 | testClassesDir属性已从" 测试"任务中删除 | 改用testClassesDirs | 是,若有,则需要修改 |
Java构建 | 从JDepend任务和SourceSetOutput中都删除了classesDir属性 | 改用JDepend.classesDirs和SourceSetOutput.classesDirs属性 | 是,若有,则需要修改 |
Java构建 | JavaBasePlugin.configureForSourceSet()方法已被删除 | 是,若有,则需要修改 | |
Java构建 | 不可以创建自己的JavaPluginConvention , ApplicationPluginConvention , WarPluginConvention , EarPluginConvention , BasePluginConvention和ProjectReportsPluginConvention实例 | 是,若有,则需要修改 | |
Tasks & properties | 删除了以下属性 | 使用ObjectFactory.property()创建Property实例 | 是,若有,则需要修改 |
Tasks & properties | 删除了内部的@Option和@OptionValues注释 | 改用公共@Option和@OptionValues | 是,若有,则需要修改 |
Tasks & properties | 删除了Task.deleteAllActions()方法 | 是,若有,则需要修改 | |
Tasks & properties | 删除了Task.dependsOnTaskDidWork()方法 | 改用声明的输入和输出 | 是,若有,则需要修改 |
Tasks & properties | 删除了TaskInternal的以下属性和方法 | 重用的实用程序方法或Worker API代替直接执行任务 | 是,若有,则需要修改 |
Kotlin DSL | Artifact配置访问器现在具有NamedDomainObjectProvider |
请参阅Gradle Kotlin DSL发行说明 | 是,若有,则需要修改 |
Kotlin DSL | PluginAware.apply |
请参阅Gradle Kotlin DSL发行说明 | 是,若有,则需要修改 |
其他 | ConfigurableReport.setDestination(Object)方法已被删除 | 改用ConfigurableReport.setDestination(File) | 是,若有,则需要修改 |
其他 | Signature.setFile(File)方法已被删除,只读的Signature.toSignArtifact属性已被删除 | 是,若有,则需要修改 | |
其他 | @DeferredConfigurable批注已被删除 | 是,若有,则需要修改 | |
其他 | 方法isDeferredConfigurable()已从ExtensionSchema中删除 | 是,若有,则需要修改 | |
其他 | .IdeaPlugin.performPostEvaluationActions()和EclipsePlugin.performPostEvaluationActions()已被删除 | 是,若有,则需要修改 | |
其他 | BroadcastingCollectionEventRegister.getAddAction()方法已被删除 | 是,若有,则需要修改 | |
其他 | 内部的org.gradle.util软件包默认不再导入 | 显式导入 | 是,若有,则需要修改 |
其他 | Tooling API不能再使用Gradle 2.6以下的Gradle版本连接到构建 | 升级到3.0 | 是,若有,则需要修改,可能也涉及到QA的改动 |
接下来,开撸:
#升级Android Studio
首先,要升级一下Android Studio:Android Studio -> check for updates...
点击之后就会出现让你升级的按钮,耐心的等一会:
升级的过程中会报错,如果不继续就无法继续升级,好吧:
升级完成之后效果:
重启之后就是漫长的等待,没事,它等待它的,我们看看这Android Studio 3.5都干了啥:
Android Gradle 插件 3.5.0 和 Android Studio 3.5 是一个重大版本,同时也是 Project Marble 计划的成果,该计划主要围绕 Android 开发者工具的三大核心领域进行改进,分别是系统运行状况、功能完善和错误修复。值得注意的是,本次更新的重中之重是提高项目的构建速度。
要详细了解这些更新以及其他 Project Marble 更新,请参阅 Android 开发者博文或以下几个部分的内容。
此版本的 Android 插件需要使用以下工具:
Gradle 5.4.1 或更高版本。要了解详情,请阅读有关更新 Gradle 的部分。
3.5.3(2019 年 12 月)
本次要更新对 Android Studio 3.5.3 构成补充,修复了各种错误并做出了多项性能改进。
3.5.2(2019 年 11 月)
本次要更新对 Android Studio 3.5.2 构成补充,修复了各种错误并做出了多项性能改进。要查看重要问题修复列表,请阅读版本更新博客上的相关博文。
3.5.1(2019 年 10 月)
本次要更新对 Android Studio 3.5.1 构成补充,修复了各种错误并做出了多项性能改进。要查看重要问题修复列表,请阅读版本更新博客上的相关博文。
##增量注释处理
如果您在 gradle.properties 文件中设置了 android.databinding.incremental=true,数据绑定注释处理器支持增量注释处理。这项优化提高了增量构建的性能。要查看经过优化的注释处理器的完整列表,请参阅增量注释处理器表格。
此外,KAPT 1.3.30 及更高版本也支持增量注释处理器,您可以通过在 gradle.properties 文件中添加 kapt.incremental.apt=true 来启用此支持。
##可缓存的单元测试
通过将 includeAndroidResources 设置为 true,您可以允许单元测试使用 Android 资源、资产和清单,此时 Android Gradle 插件会生成包含绝对路径的测试配置文件,绝对路径会打破缓存可再定位性。您可以指示插件使用相对路径生成测试配置,以便通过在 gradle.properties 文件中添加以下内容来完全缓存 AndroidUnitTest 任务:
android.testConfig.useRelativePath = true
##已知问题
在使用 Kotlin Gradle 插件 1.3.31 或更早版本时,您可能会在构建或同步项目时看到以下警告:
WARNING: API 'variant.getPackageLibrary()' is obsolete and has been replaced
with 'variant.getPackageLibraryProvider()'.
要解决此问题,请将插件升级到 1.3.40 或更高版本。
##推荐内存设置
现在,如果 Android Studio 检测到您可以通过增加操作系统应该为 Android Studio 进程(例如核心 IDE、Gradle 守护进程和 Kotlin 守护进程)分配的 RAM 上限来提高性能,它会通知您。您可以通过点击通知中的操作链接来接受推荐设置,或者,您可以通过以下方式手动调整这些设置:依次选择 File > Settings(或者,在 macOS 上依次选择 Android Studio > Preferences),然后在 Appearance & Behavior > System Settings 下找到 Memory Settings 部分。
##内存使用情况报告
Android Studio 中的内存问题有时难以重现和报告。为了解决此问题,您可以在 Android Studio 中从菜单栏依次点击 Help > Analyze Memory Usage,生成内存使用情况报告。执行此操作后,Android Studio 会在本地清理掉数据中的个人信息,然后询问您是否希望将数据发送给 Android Studio 团队以帮助识别内存问题的来源。
PS:不过这个功能对开发而言好像没啥用。
##Windows:防病毒文件 I/O 优化
Android Studio 现在会自动检查某些项目目录是否已从实时防病毒扫描中排除。当能够进行调整以提高构建性能时,Android Studio 会通知您并提供有关如何优化防病毒配置的说明。
PS:Mac表示没有此类困扰
##Apply Changes:
借助 Apply Changes,您可以将代码和资源更改推送给正在运行的应用,而无需重启应用(在某些情况下,甚至无需重启当前的 Activity)。Apply Changes 实现了一种全新的方法来保持应用的状态。与重写 APK 字节码的 Instant Run 不同,Apply Changes 会利用 Android 8.0(API 级别 26)或更高版本中支持的运行时插桩,实时地重新定义类。
##Layout Editor
Android Studio 3.5 对布局可视化、管理和互动功能进行了多项改进。
使用 ConstraintLayout 时,Attributes 面板中新的 Constraints 部分会列出所选界面组件的约束关系。您可以从设计图面或约束列表中选择一个约束条件,突出显示这两个区域中的约束条件。
同样,您现在可以选择某个约束条件并按 Delete 键,删除约束条件。您还可以按住 Control 键(在 macOS 上,按住 Command)并点击约束条件定位点来删除约束条件。请注意,当您按住 Control 或 Command 键并将鼠标悬停在定位点上时,任何关联的约束条件都会变成红色,表示您可以点击以将其删除。
选择视图后,您可以点击 Attributes 面板的 Constraint Widget 部分的任何一个 + 图标来创建约束条件,如下图所示。当您创建新的约束条件时,Layout Editor 现在会选择并突出显示该约束条件,为您刚刚添加的约束条件提供即时视觉反馈。
##NDK 并排版本
现在,您可以并排使用 NDK 的多个版本。此功能可让您更灵活地配置项目,例如,如果项目在同一计算机上使用了不同版本的 NDK。
如果您的项目使用 Android Gradle 插件 3.5.0 或更高版本,您还可以指定项目中每个模块应使用的 NDK 版本。您可以使用此功能来创建可重现的构建版本,并缓解 NDK 版本与 Android Gradle 插件之间的不兼容性。
##从4.10更新过来的同学看这里
接下来我们来说说,Gradle升级的好处:
如果您尚未使用4.10版本,请跳至适用于当前Gradle版本的部分,然后逐步升级,直至到达此处. 然后,从Gradle 4.10移至5.0时应用这些更改.
1.不再需要enableFeaturePreview('IMPROVED_POM_SUPPORT')和enableFeaturePreview('STABLE_PUBLISHING')标志. 现在默认情况下启用了这些功能.
2.Gradle现在捆绑了Java 9及更高版本的JAXB . 您可以从org.gradle.jvmargs删除--add-modules java.xml.bind选项(如果已设置).
##其他可能会出现问题的点
1.对publishing {}块的评估不再推迟到需要时才执行,但其行为与其他任何块一样. 如果您需要推迟评估,请使用afterEvaluate {} .
2.Javadoc和Groovydoc任务现在在执行之前删除了文档的目标目录. 已添加它以从上一次任务执行中删除过时的输出文件.
3.Java库分发插件现在基于Java库插件而不是Java插件 .
在应用Java插件时,其行为略有不同(例如,它添加了api配置). 因此,请确保在升级后检查内部版本是否符合预期.
4.CheckstyleReport和FindBugsReport的html属性现在返回一个CustomizableHtmlReport实例,该实例更易于从静态类型的语言(如Java和Kotlin)进行配置.
5.以下重大更改将在Gradle 4.10中作为弃用警告显示:
##General
<<对于任务定义不再有效. 换句话说,您不能使用语法task myTask << { … } .
改用Task.doLast()方法,如下所示:
task myTask {
doLast {
...
}
}
您不能再在域对象名称中使用以下任何字符,例如项目和任务名称:
##Running Gradle & build environment
如前所述,Gradle不能再在Java 7上运行.但是,您仍然可以使用派生的编译和测试来构建和测试Java 6及更高版本的软件.
1.The -Dtest.single command-line option has been removed — use test filtering instead.
2.-Dtest.debug命令行选项已删除-使用--debug-jvm选项代替.
3.-u / --no-search-upward命令行选项已被删除-确保所有构建均具有settings.gradle文件.
4.--recompile-scripts命令行选项已删除.
5.除非嵌套的构建具有settings.gradle文件,否则您不能再将Gradle嵌套在另一个Gradle构建的子目录中.
6.DirectoryBuildCache.setTargetSizeInMB(long)方法已被删除-改用DirectoryBuildCache.removeUnusedEntriesAfterDays .
7.org.gradle.readLoggingConfigFile系统属性不再执行任何操作-更新受影响的测试以使用您的java.util.logging设置.
文件操作
1.您不再可以使用as关键字或asType()方法将FileCollection对象转换为其他类型.
2.您不能再传递null作为CopySpec.from(Object,Action)的配置操作.
3.为了与Kotlin DSL更好地兼容, CopySpec.duplicatesStrategy不再可以为空. 属性设置器不再接受null作为将属性重置为其默认值的方法. 请改用DuplicatesStrategy.INHERIT .
4.FileCollection.stopExecutionIfEmpty()方法已被删除-在FileCollection任务属性上使用@SkipWhenEmpty批注.
FileCollection.add()方法已删除-使用Project.files()和Project.fileTree()创建可配置的文件集合/文件树,并通过ConfigurableFileCollection.from()将其添加到它们.
5.SimpleFileCollection已被删除-改为使用Project.files(Object ...) .
6.没有您自己的类扩展AbstractFileCollection改用Project.files()方法. 此问题可能表现为缺少的getBuildDependencies()方法.
##Java构建
1.CompileOptions.bootClasspath属性已被删除,请改用CompileOptions.bootstrapClasspath .
2.您不能再将-source-path用作通用编译器参数,而应改用CompileOptions.sourcepath .
3.您不能再将-processorpath用作通用编译器参数,而应改用CompileOptions.annotationProcessorPath .
4.Gradle将不再自动应用编译类路径上的注释处理器,而应改用CompileOptions.annotationProcessorPath .
5.testClassesDir属性已从" 测试"任务中删除-改用testClassesDirs .
6.从JDepend任务和SourceSetOutput中都删除了classesDir属性. 请改用JDepend.classesDirs和SourceSetOutput.classesDirs属性.
7.JavaLibrary(PublishArtifact, DependencySet)构造函数— Shadow Plugin使用了该构造函数,因此请确保至少升级到该插件的2.x版本.
8.JavaBasePlugin.configureForSourceSet()方法已被删除.
9.您不再可以创建自己的JavaPluginConvention , ApplicationPluginConvention , WarPluginConvention , EarPluginConvention , BasePluginConvention和ProjectReportsPluginConvention实例.
10.Maven插件用于发布过时的Maven 2元数据格式. 它已更改,现在将发布Maven 3元数据,就像Maven Publish插件一样.
随着Maven 2支持的删除,配置唯一快照行为的方法也已删除. Maven 3仅支持唯一的快照,因此我们决定删除它们.
##Tasks & properties
1.删除了以下与惰性属性相关的旧类和方法-使用ObjectFactory.property()创建Property实例:
PropertyState
DirectoryVar
RegularFileVar
ProjectLayout.newDirectoryVar()
ProjectLayout.newFileVar()
Project.property(Class)
Script.property(Class)
ProviderFactory.property(Class)
使用任务配置避免 API配置和注册的任务对可以从配置操作中调用的其他方法有更多限制.
2.内部的@Option和@OptionValues注释(软件包org.gradle.api.internal.tasks.options )已被删除. 请改用公共@Option和@OptionValues批注.
3.Task.deleteAllActions()方法已被删除,无法替代.
4.Task.dependsOnTaskDidWork()方法已被删除-改用声明的输入和输出 .
5.已删除TaskInternal的以下属性和方法-使用任务依赖项,任务规则,可重用的实用程序方法或Worker API代替直接执行任务.
execute()
executer
getValidators()
addValidator()
TaskInputs.file(Object)方法不能再使用可解析为单个常规文件以外的任何参数的参数来调用.
TaskInputs.dir(Object)方法不能再使用解析为单个目录以外的任何参数的参数来调用.
您不再可以通过TaskInputs和TaskOutputs注册无效的输入和输出.
TaskDestroyables.file()和TaskDestroyables.files()方法已被删除-改用TaskDestroyables.register() .
SimpleWorkResult已被删除-使用WorkResult.didWork .
现在,覆盖4.8中弃用的内置任务会产生错误.
尝试替换内置任务将产生类似于以下内容的错误:
Cannot add task 'wrapper' as a task with that name already exists.
Scala & Play
不再支持Play 2.2-请升级您使用的Play版本.
ScalaDocOptions.styleSheet属性已被删除-Scala 2.11.8及更高版本中的Scaladoc Ant任务不再支持此属性.
##Kotlin DSL
Artifact配置访问器现在具有NamedDomainObjectProvider
PluginAware.apply
两项更改都可能导致脚本编译错误. 请参阅Gradle Kotlin DSL发行说明,以获取更多信息以及如何修复因上述更改而损坏的构建.
##Miscellaneous
1.ConfigurableReport.setDestination(Object)方法已被删除-改用ConfigurableReport.setDestination(File) .
2.Signature.setFile(File)方法已被删除-Gradle不支持更改生成的签名的输出文件.
只读的Signature.toSignArtifact属性已被删除-永远不应成为公共API的一部分.
3.@DeferredConfigurable批注已被删除.
4.方法isDeferredConfigurable()已从ExtensionSchema中删除.
5.IdeaPlugin.performPostEvaluationActions()和EclipsePlugin.performPostEvaluationActions()已被删除.
6.The `BroadcastingCollectionEventRegister.getAddAction()方法已被删除,无法替代.
7.内部的org.gradle.util软件包默认不再导入.
理想情况下,您不应该使用此程序包中的类,但是,作为一种快速解决方案,您可以将显式导入添加到这些类的构建脚本中.
8.The gradlePluginPortal() repository no longer looks for JARs without a POM by default.
9.Tooling API不能再使用Gradle 2.6以下的Gradle版本连接到构建. 通过TestKit运行的构建也是如此.
10.Gradle 5.0需要最低版本的Tooling API客户端版本3.0. 较旧的客户端库无法再使用Gradle 5.0运行构建.
11.IdeaModule Tooling API模型元素包含用于检索资源和测试资源的方法,因此这些元素已从IdeaModule.getSourceDirs()和IdeaModule.getTestSourceDirs()的结果中删除.
In previous Gradle versions, the source field in SourceTask was accessible from subclasses. This is not the case anymore as the source field is now declared as private.
12.在Worker API中, 不能再设置worker的工作目录 .
与依赖关系和版本约束有关的行为更改可能会影响少量用户.
对DefaultTask上的属性工厂方法进行了一些更改,这些更改可能会影响自定义任务的创建.
#升级Gradle和Gradle插件
升级跟砍传奇一样,只有你升级了之后才之后哪些是报错,哪些不是报错,报错了一个一个解决,都解决完成,升级完成。
##报错一
ERROR: Unable to resolve dependency for ':58WuxianClient@wubaDebug/compileClasspath': Could not resolve com.anjuke.mobile:sign:1.1.2-SNAPSHOT.
##报错二
com.facebook.imagepipeline.image.CloseableAnimatedImage 错误:找不到符号
解决:经排查是因为"com.facebook.fresco:animated-base"这个库找不到导致,在原来的版本上是可以有这一层依赖的。它是在animated-gif下,不过目前看到的是没有的。所以,最后添加了对此库的依赖。
##报错三
transformClassesAndResourcesWithR8ForWubaRelease FAILED
解决:这是R8编译时发生的错误,禁止R8即可;
Disables R8 for Android Library modules only.
android.enableR8.libraries = false
Disables R8 for all modules.
android.enableR8 = false
##报错四
Caused by: com.android.tools.r8.utils.AbortException: Error: null, Cannot fit requested classes in the main-dex file (# methods: 69437 > 65536)
[exec] at com.android.tools.r8.utils.Reporter.a(:21)
[exec] at com.android.tools.r8.utils.Reporter.a(:7)
[exec] at com.android.tools.r8.dex.VirtualFile.a(:33)
[exec] at com.android.tools.r8.dex.VirtualFile$e.a(:37)
[exec] at com.android.tools.r8.dex.ApplicationWriter.a(:13)
[exec] at com.android.tools.r8.dex.ApplicationWriter.write(:35)
[exec] at com.android.tools.r8.D8.d(:44)
[exec] at com.android.tools.r8.D8.b(:1)
[exec] at com.android.tools.r8.utils.t.a(:23)
分析:目前有两种方案,一种是没有配置multidex,一种是java的JDK没有升级1.8
添加了android.enableD8=false之后,发现会报错:
Java 8 language support, as requested by 'android.enableD8.desugaring= true' in your gradle.properties file, is not supported when 'android.enableD8= false'
现在反向思路解决不了问题,咱们就正向解决,让它放在main-dex里面,然后再分析,先保证打包能过去;
去掉了一些文件在主dex之后,继续开启编译之路,但是很快,就遇到了新的问题:
##报错五
com.android.tools.build.apkzlib.zip.compress.Zip64NotSupportedException: Zip64 EOCD locator found but Zip64 format is not supported: /opt/build/temp/74638/beta/android/58WuxianClient/build/intermediates/transforms/proguard/wuba/release/0.jar
从字面意思分析是从配置上支持了使用Zip64打包APK,但是发现我们release下的jar包不支持。那大概有两种思路,一种是让我们的包支持zip64,另外一种是想办法把zip64禁用。
我尝试了本地打包,居然通过了,看的我老泪纵横:
Tasks spend time > 50ms:
04:25.78 :58WuxianClient:multiDexListWubaDebug
04:17.27 :58WuxianClient:transformClassesWithDexBuilderForWubaDebug
02:41.24 :58WuxianClient:javaPreCompileWubaDebug
01:29.50 :58WuxianClient:mergeWubaDebugResources
01:06.02 :58WuxianClient:checkConflictDependencies
00:55.43 :58WuxianClient:mergeDexWubaDebug
00:46.11 :58WuxianClient:processWubaDebugResources
00:30.93 :58WuxianClient:mergeWubaDebugNativeLibs
00:28.55 :58WuxianClient:compileWubaDebugJavaWithJavac
00:24.20 :58WuxianClient:packageWubaDebug
00:21.95 :58WuxianClient:mergeWubaDebugJavaResource
00:19.80 :58WuxianClient:checkWubaDebugDuplicateClasses
00:14.39 :58WuxianClient:stripWubaDebugDebugSymbols
00:12.02 :58WuxianClient:processWubaDebugManifest
00:05.95 :58WuxianClient:transformClassesWithAjxForWubaDebug
00:04.09 :PublishDex:javaPreCompileDebug
00:03.39 :PublishDex:mergeDebugJavaResource
00:03.17 :PublishDex:transformClassesWithDexBuilderForDebug
00:02.84 :PublishDex:mergeExtDexDebug
00:02.67 :58WuxianClient:transformClassesWithCom.alibaba.arouterForWubaDebug
00:02.56 :PublishDex:compileDebugJavaWithJavac
00:02.29 :PublishDex:processDebugResources
00:01.87 :58WuxianClient:mergeWubaDebugAssets
00:01.04 :PublishDex:packageDebug
00:00.68 :PublishDex:processDebugManifest
00:00.63 :PublishDex:mergeDebugResources
00:00.26 :PublishDex:mergeDexDebug
00:00.22 :58WuxianClient:clean
00:00.11 :PublishDex:generateDebugBuildConfig
00:00.10 :PublishDex:checkDebugManifest
00:00.08 :PublishDex:preBuild
00:00.07 :58WuxianClient:mergeWubaDebugShaders
BUILD SUCCESSFUL in 11m 4s
53 actionable tasks: 53 executed
bjdhj-124-7:58ClientProject $
看了一下具体的区别,发现我们是没有构建release的包的过程,本地目前用的是debug,而AVM用的是Release构建,想到这,我发现有一个配置:useProguard true,跟我本地配置是不太一样的。
解决:
查看配置文件,发现我们配置了:android.useDeprecatedNdk=true,所以直接去掉就行了,编译器会自动帮我们做。
#问题六
Cannot get the value of write-only property 'isSourceDependency' for script of type ajk_dependencies_dq8xyz4cdpugj2rk4pphbca0e.
//用户标识是否为源码依赖,修改 isSourceDependency 可实现全局aar依赖或源码依赖
@Field def isSourceDependency = true
A problem occurred configuring project ':58AnjukeLib'.
[exec] > compileSdkVersion is not specified.
#问题七
Task :58WuxianClient:transformClassesWithMultidexlistForWubaRelease
multiDexTask.name transformClassesWithMultidexlistForWubaRelease
[collectWubaDebugMultiDexComponents, collectWubaReleaseMultiDexComponents]
multiDexBuildMainlistTask.nametransformClassesWithMultidexlistForWubaRelease
[transformClassesWithMultidexlistForWubaDebug,transformClassesWithMultidexlistForWubaRelease]
这个task没有执行导致task无法正常运行;
但是,下面这个task就执行了,咱们看看人家为啥执行:
Task :58WuxianClient:transformClassesWithNewLensTransformForWubaRelease
看不出来,咱们缺的task还有:
Task :58WuxianClient:transformClassesWithDexBuilderForWubaRelease
Task :58WuxianClient:transformClassesWithMultidexlistForWubaRelease
事实证明人家就是把transformClassesWithDexBuilderForxxx这个task给删除了;或者说人家执行了 ,但是压根没给你暴露出来
解决办法:
#问题八
def isSourceDependency 报错找不到:修改为: ext { isSourceDependency = true }
#问题九
官方的API描述:task的getFile方法描述:Returns the output files of this task.但是我没有找到
https://docs.gradle.org/5.4.1/javadoc/org/gradle/api/tasks/TaskOutputs.html
#问题十
使用R8一直报错,总是报
58WuxianClient:transformClassesAndResourcesWithR8ForWubaRelease in 58AnjukeLib Finished
R8: Cannot fit requested classes in the main-dex file (# methods: 66075 > 65536)
咱们已经使用R8了,而且已经配置了multidex但是依然还是不生效,仔细一看,果然是因为这个lib没有单独做配置;导致它打包的时候全都在主dex里面;
那是不是所有的库,都需要这么配置呢?
#问题十一
[exec] 05:38.92 :58WuxianClient:transformClassesAndResourcesWithR8ForWubaRelease
[exec] 02:41.08 :58WuxianClient:mergeWubaReleaseJavaResource
[exec] 02:11.56 :58WuxianClient:transformClassesWithNewLensTransformForWubaRelease
[exec] 01:17.21 :58WuxianClient:resguardWubaRelease
[exec] 00:51.20 :58WuxianClient:packageWubaRelease
[exec] 00:25.99 :58WuxianClient:transformClassesWithWmdaInjectForWubaRelease
[exec] 00:21.68 :58WuxianClient:processWubaReleaseResources
[exec] 00:19.77 :58WuxianClient:mergeWubaReleaseResources
[exec] 00:09.78 :58WuxianClient:checkConflictDependencies
[exec] 00:08.49 :58WuxianClient:compileWubaReleaseJavaWithJavac
[exec] 00:03.56 :58WuxianClient:javaPreCompileWubaRelease
[exec] 00:02.37 :58WuxianClient:processWubaReleaseManifest
[exec] 00:02.30 :58WuxianClient:transformClassesWithAjxForWubaRelease
[exec] 00:01.13 :58WuxianClient:mergeWubaReleaseAssets
[exec] 00:00.93 :58WuxianClient:stripWubaReleaseDebugSymbols
[exec] 00:00.88 :58WuxianClient:transformClassesWithCom.alibaba.arouterForWubaRelease
[exec] 00:00.06 :58WuxianClient:mergeWubaReleaseGeneratedProguardFiles
#问题十二
折腾来折腾去,最终发现我们的老方法已经行不通了,而且它已经使用了3年了,是时候使用正规的混淆方法了。
dexOptions {
...
additionalParameters = [//dex参数详见 dx --help
'--multi-dex', //多分包
'--set-max-idx-number=55000', //每个包内方法数上限
//'--main-dex-list=' + projectDir +
//'/maindexlist.txt', //打包进主classes.dex的文件列表
//'--minimal-main-dex' //使上一句生效
...
]
}
#问题十三
Java 8 language support, as requested by 'android.enableD8.desugaring= true' in your gradle.properties file, is not supported when 'android.enableD8= false'
使用方式的变化
不再需要使用 apply plugin:'com.android.application',如果您是 portal 工程,仅仅需要 apply plugin:'com.alipay.portal'。
如果您是 bundle 工程,也需要删除 apply plugin:'com.android.application', 仅需要使用 apply plugin:'com.alipay.bundle'。
library 工程依然使用 apply plugin:'com.android.library'。
如果使用最新稳定版本 Android Studio 3.5 或以上,那么您需要在 gradle.properties 里面新增 android.buildOnlyTargetAbi=false。
由于我们的无线保镖组件暂不支持 V2 签名,如果您需要使用 Android Studio 调试并安装您的 APK,那么您需要禁用 V2 签名;如果您使用命令行进行构建,且您的 minSdkVersion 大于等于 24,则您也需要禁用 V2 签名。禁用 V2 签名的方式如下:
v2SigningEnabled false
#问题十四
DX和D8的区别
#问题十五
AAPT2 aapt2-3.5.3-5435860-linux Daemon #0: shutdown
[exec] R8: The rule -keep class * extends com.facebook.react.bridge.JavaScriptModule { [exec] *; [exec] }
uses extends but actually matches implements.
R8: The rule -keep public class * extends androidx.versionedparcelable.VersionedParcelable { [exec] <init>(); [exec] }
uses extends but actually matches implements.
[exec] AAPT2 aapt2-3.5.3-5435860-linux Daemon #1: shutd
R8: The rule -keep class * extends com.facebook.react.bridge.JavaScriptModule { [exec] *; [exec] }
uses extends but actually matches implements.
解决:这是versionedparcelable 1.0.0的bug,在1.1.0版本已经修改,修改方法:
https://r8.googlesource.com/r8/+/6a4e7c1dc82838cefc5ef5964186fa088ad9bee1/src/main/java/com/android/tools/r8/naming/signature/GenericSignatureRewriter.java
1、在proguard文件中添加:
-keep public class * implements androidx.versionedparcelable.VersionedParcelable
2、在build.gradle文件中添加:
implementation "androidx.versionedparcelable:versionedparcelable:1.1.0"
3、在build.gradle中添加:
packagingOptions {
exclude 'META-INF/androidx.versionedparcelable_versionedparcelable.version'
}
#问题十六
R8: Invalid signature 'Lcom/squareup/haha/guava/collect/AbstractMapBasedMultimap<TK;TV;>.com/squareup/haha/guava/collect/AbstractMapBasedMultimapWrappedSortedSet.
[exec] Signature is ignored and will not be present in the output.
[exec] Parser error: Expected ; at position 70
#问题十七
我有一个相关的错误,但与React Native 0.47.1略有不同:
java.lang.NoSuchFieldError: no "Lcom/facebook/jni/HybridData;" field "mHybridData" in class "Lcom/facebook/react/bridge/JavaScriptExecutor;" or its superclasses
at com.facebook.react.bridge.CatalystInstanceImpl.initializeBridge(Native Method)
at com.facebook.react.bridge.CatalystInstanceImpl.
at com.facebook.react.bridge.CatalystInstanceImpl.
at bnv.a(SourceFile:574)
at bmg.a(SourceFile:999)
at bmg.a(SourceFile:109)
at bmg$4.run(SourceFile:802)
at java.lang.Thread.run(Thread.java:761)
我必须在我的Proguard文件中添加稍微不同的行来修复:
-keep class com.facebook.react.bridge.CatalystInstanceImpl { *; }
-keep class com.facebook.react.bridge.JavaScriptExecutor { *; }
-keep class com.facebook.react.bridge.queue.NativeRunnable { *; }
-keep class com.facebook.react.bridge.ReadableType { *; }
#问题十八
R8: Missing class: org.apache.harmony.xnet.provider.jsse.OpenSSLSocketImplWrapper
[exec] R8: Missing class: org.springframework.http.converter.GenericHttpMessageConverter
[exec] R8: Missing class: org.apache.harmony.xnet.provider.jsse.OpenSSLSocketImpl
[exec] R8: Missing class: org.glassfish.jersey.internal.spi.AutoDiscoverable
[exec] R8: Missing class: org.springframework.messaging.converter.AbstractMessageConverter
[exec] R8: Missing class: com.android.org.conscrypt.OpenSSLSocketImplWrapper
[exec] R8: Missing class: com.huawei.android.app.HwMultiWindowExCellInfoCallback
[exec] R8: Missing class: org.springframework.web.servlet.mvc.method.annotation.ResponseBodyAdvice
[exec] R8: Missing class: org.springframework.http.converter.AbstractHttpMessageConverter
[exec] R8: Missing class: org.springframework.data.redis.serializer.RedisSerializer
[exec] R8: Missing class: android.arch.paging.PositionalDataSource
[exec] R8: Missing class: org.springframework.web.servlet.view.AbstractView
##问题十九
proguard.txt 里面有一个...那个问题得解决
##问题二十
For native methods, see http://proguard.sourceforge.net/manual/examples.html#native
-keepclasseswithmembernames class * {
native
}
-keepclasseswithmembernames,includedescriptorclasses class * {
native
}
在混淆里面加入
##问题二十一
- What went wrong:
[exec] Execution failed for task ':58WuxianClient:transformClassesAndResourcesWithR8ForWubaRelease'.
[exec] > java.util.NoSuchElementException (no error message)
这是因为使用了不匹配的buildToolsVersion,将其改为buildToolsVersion=29.0.2好了
##问题二十二
发布AAR报错
就在我以为我可以的时候,突然间发布AAR报错了,老子万念俱灰;
Publishing a build scan to scans.gradle.com requires accepting the Gradle Terms of Service defined at https://gradle.com/terms-of-service. Do you accept these terms? [yes, no]
The response from https://scans-in.gradle.com/in/5.6.4/2.4.2 was not from the build scan server.
Your network environment may be interfering, or the service may be unavailable.
If you believe this to be in error, please report this problem via https://gradle.com/scans/help/plugin and include the following via copy/paste:
Gradle version: 5.6.4
Plugin version: 2.4.2
Request URL: https://scans-in.gradle.com/in/5.6.4/2.4.2
Request ID: 0bcae986-da07-4567-a4b2-5a32fd4079b0
Response status code: 502
Response content type: text/html
Response server type: cloudflare
Task has not declared any outputs despite executing actions
Task ':WubaCommonsLib:mergeDebugNativeLibs' is not up-to-date because:
Output property 'cacheDir' file /Users/huhao/AndroidStudioProjects/wuba/58ClientProject/WubaCommonsLib/build/intermediates/incremental/debug-mergeNativeLibs/zip-cache has been removed.
Output property 'outputDir' file /Users/huhao/AndroidStudioProjects/wuba/58ClientProject/WubaCommonsLib/build/intermediates/merged_native_libs/debug/out has been removed.
Output property 'outputDir' file /Users/huhao/AndroidStudioProjects/wuba/58ClientProject/WubaCommonsLib/build/intermediates/merged_native_libs/debug/out/lib has been removed.
https://s0docs0gradle0org.icopy.site/current/dsl/org.gradle.api.publish.maven.MavenPublication.html maven发布报错
https://www.icode9.com/content-4-493255.html
##参考链接
https://developer.android.google.cn/studio/releases/gradle-plugin?hl=zh_cn
https://www.jianshu.com/p/13a62e1ac396
https://developer.android.google.cn/studio/releases/gradle-plugin#updating-gradle
https://blog.csdn.net/Gdeer/article/details/83106449
https://www.jianshu.com/p/9eb063fa9c79
https://juejin.im/entry/5a7807926fb9a063517250b1
https://help.aliyun.com/knowledge_detail/151447.html?spm=5176.13910061.0.0.153b3a2dPjuJZs&aly_as=mBoSMf9d
https://docs.gradle.org/5.4.1/javadoc/
https://www.jianshu.com/p/f2cd43e488a6
https://r8.googlesource.com/r8
https://blog.csdn.net/xiongya8888/article/details/94446803
https://blog.csdn.net/xyq046463/article/details/102929528?depth_1-utm_source=distribute.pc_relevant.none-task&utm_source=distribute.pc_relevant.none-task
https://developer.android.com/studio/command-line/d8
https://developer.android.com/studio/build/multidex?hl=zh-cn
https://d.android.com/r/studio-ui/d8-overview.html
https://developer.android.com/studio/build/multidex
https://developer.android.com/studio/build/apk-analyzer
https://www.guardsquare.com/en/products/proguard/manual/usage#keepoptions
https://www.jianshu.com/p/dd932f951137 官网建议
https://developer.android.com/studio/build/shrink-code#java R8优化
https://www.guardsquare.com/en/blog/proguard-and-r8 混淆优化说明
https://fucknmb.com/2019/05/28/R8-%E8%B8%A9%E5%9D%91%E8%AE%B0/ R8踩坑记
https://fucknmb.com/2017/06/01/Android-Gradle-Plugin%E6%BA%90%E7%A0%81%E9%98%85%E8%AF%BB%E4%B8%8E%E7%BC%96%E8%AF%91/
gradle源码查看
https://www.jianshu.com/p/11f030b2034f gradle插件源码查看
https://android.googlesource.com/platform/tools/base/+/studio-master-dev/build-system/gradle-core/src/main/java/com/android/build/gradle/internal/scope/VariantScopeImpl.java
https://zhuanlan.zhihu.com/p/62794593 关于脱糖
https://www.cnblogs.com/skymxc/p/gradle-custom-plugin.html 开发一个gradle插件
https://juejin.im/post/5c5bee986fb9a049bc4d1b58 缩减MainDex大小
https://r8.googlesource.com/r8/+/refs/heads/master/compatibility-faq.md