昨天,官网(https://developer.android.com/) 更新了Androd studio 版本和 gradle-plugin 版本,迫不及待尝试下,针对自己的项目做了些相应的修改,相比之前,这个版本的改动是最多的,出来了许多新特性。下面总结下升级过程中遇到的坑。
1. 升级大概流程:
- 1)升级 gradle 版本:
|
|
- 2)修改 maven 仓库:
|
|
- 3)升级 gradle-plugin 插件版本:
|
|
2. 踩到的坑以及插件变更的方面:
1) META-INF/MANIFEST.MF 问题:
|
|
|
|
2) 依赖问题:
|
|
按照后面改进的依赖方式配置
3) AAPT2 问题:
|
|
在根项目的 gradle.properties 文件中添加:
|
|
4) flavor dimension 必须设置:
|
|
依赖机制改动:在使用 library 时会自动匹配 variant(debug、release),即 app 的 debug 会自动匹配 library 的 debug;同样地,如果使用 flavor 的时候,比如 app 的 freeDebug 也会自动匹配 library 的 freeDebug。尽管如此,但在使用到 flavor 时,必须为所有的 flavor 配置一个 flavor dimension
|
|
6) 依赖配置:
解决依赖构建错误: 如果 app 依赖 library A, app 的 buildType 为 debug、rtest、release, 但是 library buildType 只有 debug、release,当构建 debug app 的时候,插件会自动去寻找 library rtest,最后会发现不到,错误信息如下:
|
|
出现该错误的原因大致可以分为三类:
- app 存在的 buildType,但是 library 没有;通过 matchingFallbacks 去给 buildType 设置依赖:
|
|
- 对于 app 和 library 都存在的 flavor dimension,app 中存在的 flavor,但是 library 没有;通过 matchingFallbacks 去给 flavor 设置依赖:
|
|
- library 依赖包括的 flavor dimension,但是 app 没有:通过 missingDimensionStrategy 在 defaultConfig 中指定默认的 flavor, 这样插件找不到 dimension 时,就会去使用默认的 flvor;同时也可以在 productFlavors 中为每个匹配指定默认的 flavor:
|
|
7) 本地模块以来配置:自动匹配 variant 的机制,无须手动指定 variant 的配置,而且不支持如下配置了:
|
|
可修改为以下配置:
|
|
8) Gradle 3.4 引入了新的 Java 库插件配置, 允许您控制是否将依赖项发布到使用该库的项目的编译和运行时路径。Android 插件正在采用这些新的依赖配置, 迁移大型项目来使用它们可以大大缩短构建时间。
新配置 | 旧配置 | 概述 |
---|---|---|
implementation | compile | module 编译时可用,但 module 的依赖者运行时可用;只在内部使用了该 module,不会向外部暴露其依赖的 module 内容 |
api | compile | module 编译时可用,module 的依赖者编译和运行时可用,和 compile 的作用一样,当前 module 会暴露其依赖的其他 module 内容 |
compileOnly | provided | module 编译时可用,但是 module 的依赖者,在编译和运行时均不可用,和之前的 provided 类似 |
runtimeOnly | apk | module 和 module 依赖者,仅仅在运行时可用 |
假如存在以下依赖:
- 第一种:
|
|
- 第二种:
|
|
- 第三种:
|
|
结论:api 与 之前的 compile 作用一样,可以传递依赖;implementation 仅仅依赖当前 module,不具有传递属性
9) 发布依赖:如下配置保存了 library 的传递依赖性, 供其使用者使用
|
|
10) 自定义依赖:如下配置来解决变量的所有依赖项
新配置(运行时) | 旧配置(编译时) |
---|---|
variant_nameRuntimeClasspath | _variant_nameCompile 不再生效 |
variant_nameCompileClasspath | _variant_nameApk 不再生效 |
如果继续使用旧有的配置,则会抛出以下错误:
|
|
由于新的依赖方式延迟了依赖 resolution, 因此可以使用 Variant API 来设置 resolution strategy:
|
|
11) 从 test 配置中排除 app 依赖项
- 原有的排除依赖方式:
|
|
- 新的排除依赖方式:这是因为 androidTestImplementation 和 androidTestApi 扩展了 Implementation 和 api 配置
|
|
12) 原有的 variant outputs 在构建时不再生效,不过新的插件仍然支持修改生成的 apk 的名称:
|
|
13) processManifest.manifestOutputFile() 方法已经废弃,如果继续使用,会抛出如下错误:
|
|
但是可以调用 processManifest.manifestOutputDirectory () 返回包含所有生成的 manifest 的目录的路径,然后可以根据需要修改某个 manifest:
|
|
14) 使用 annotation processor 依赖配置:
在之前的插件中, compile classpath 上的依赖项被自动添加到processor classpath 中。即你可以将 annotation processor添加到 compile classpath 中;但是, 通过向 processor 添加大量不必要的依赖关系, 这将对性能产生重大影响。
在 Android 3.0.0 插件中, 规定必须使用 annotationProcessor 将依赖项配置将 annotation processors 添加到 processor classpath 中:
|
|
15) 禁用 annotation processor 错误检查:
|
|
16) 使用独立的测试模块:
|
|
17) libraries 中的本地 jar 包可传递:
之前的插件在库模块中将以非标准方式处理本地 jar 的依赖关系, 并将它们打包到 aar 中;新的插件3.0.0 和新的 Gradle api, 支持本地 jar 可传递依赖性, 类似于基于 maven 的依赖关系:
在 project 中发布:
- library 模块不再处理本地 jar;
- library 模块的改变只会影响 project,PROJECT_LOCAL_DEPS 已经废弃;
- app 模块中的本地 jar 作为EXTERNAL stream 的一部分, PROJECT_LOCAL_DEPS 和 SUB_PROJECT_LOCAL_DEPS 总是为空;
- library modules 中的 ProGuard 不会影响 library 代码,只需在依赖 library 的 app 中使用 ProGuard;
- 之前,需要在 library 中解决和本地 jar 包中的资源冲突,现在需要在 app 中去解决冲突;
Maven 仓库发布:这个和之前类似,没有改变;
18) AAPT2 的变化:
- Android manifest 中元素的层级:在之前的 aapt 中,Manifest 中不正确的层级会报警告或者被忽略,如下:
|
|
之前的 aapt 只会忽略 action,然而,在最新的 AAPT2 中,将会报错:
|
|
解决方法就是按照正确的语法结构去修改,确保 manifest 元素正确
- 资源定义:不支持从 name 属性中指定资源类型,如:
|
|
上述定义资源类型将会导致如下错误:
|
|
解决方法:明确指定资源类型(type = “attr”)
|
|
此外,定义 style 元素时,它的父元素也必须是 style 资源类型,否则会导致同样的错误:
|
|
- Android ForegroundLinearLayout 中的 namespace:ForegroundLinearLayout 包括三种 foregroundInsidePadding, android:foreground, and android:foregroundGravity 三种属性,注意 android namespace 不包括 foregroundInsidePadding;在之前的 AAPT 中,编译器会忽略 foregroundInsidePadding,但是在 AAPT2 中,则会抛出错误:
|
|
解决方法:用 android:foregroundInsidePadding 替换 foregroundInsidePadding 即可:
- 不恰当地使用 @ 资源引用符号:检测到忽略或者不当使用 @ 时,AAPT2 会抛出错误,例如,当指定 style 属性时,遗漏了 @ 时
|
|
将会导致如下错误:
|
|
此外,如果不当的使用 @ 引用 android namespace 中的资源时,如下所示:
|
|
将会导致如下错误:
|
|
参考:
[1] https://developer.android.com/studio/build/gradle-plugin-3-0-0-migration.html#known_issues
[2] http://blog.csdn.net/ncuboy045wsq/article/details/73521856