更新完Android Stuido 3.0 稳定版之后,打开项目会收到如下提醒
谷歌强烈建议我们更新Android Gradle Plugin 3.0 和 Gradle 4.1,所以我就习惯性的点击了Update。
结果……导致了一系列的修改。
1、Flavor Dimensions 配置
我的项目中用了多渠道,3.0之前配置多渠道:productFlavors配置不同的渠道包,3.0 新增了flavorDimensions的配置
编译的时候报错:
Error:All flavors must now belong to a named flavor dimension. Learn more athttps://d.android.com/r/tools/flavorDimensions-missing-error-message.html
打开后面的链接查看原因。
Plugin 3.0.0 includes a new dependency mechanism that automatically matches variants when consuming a library. This means an app's redDebug variant will consume a library's redDebug variant. To make this work, the plugin now requires that all flavors belong to a named flavor dimension —even if you intend to use only a single dimension. Otherwise, you will get the following build error:
Error:All flavors must now belong to a named flavor dimension.
The flavor 'flavor_name' is not assigned to a flavor dimension.
Android Plugin3.0包含了一种新的依赖机制:在使用library时会自动匹配variant(debug, release),就是说app的debug会自动匹配library的debug。同样如果使用flavor的时候,比如app的redDebug同样会自动匹配library的redDebug。虽然有这样的优势,但是在使用flavor时,必须定义flavor dimension,否则会提示错误。
To resolve this error, assign each flavor to a named dimension, as shown in the sample below. Because dependency matching is now taken care of by the plugin, you should name your flavor dimensions carefully. For example, if all your app and library modules use the foo dimension, you'll have less control over which flavors are matched by the plugin.
// Specifies a flavor dimension.
flavorDimensions "color"
productFlavors {
red {
// Assigns this product flavor to the 'color' flavor dimension.
// This step is optional if you are using only one dimension.
dimension "color"
...
}
blue {
dimension "color"
...
}
}
现在使用flavor,必须像上面那样配置。
2、新的依赖配置
Gradle 3.4 推出了新的Java library plugin 配置:允许控制发布以编译和运行时类路径(用于模块间依赖)
通过下面一张图来说明下新的Java library plugin 配置关系:
1)绿色方块:使用者可以使用的依赖,比如:app配置library的依赖
2)粉色方块:组件对library:编译时或者运行时
3)蓝色:组件内部使用,注意这里是不用传递的,比如a依赖b,b依赖c, 但是a不能获取c的配置
4)白色:配置集成自java plugin
新配置 |
对应的过时配置 | 描述 |
---|---|---|
implementation | compile | module编译时可用,module的使用者运行时可用,对于大量使用library的项目,可以显著提高编译时间,因为它可以减少构建系统重新编译一些module.大多数app/test因为使用这种配置 |
api | compile | module编译时可用,module的使用者编译和运行时可用,这个和过时的compile一样的。一般是library模块会使用它,如果app模块一定要使用它,必须是在它想暴露api给test模块使用 |
compileOnly | provided | module 编译时可用,但是module的使用者,在编译和运行时均不可用。跟过时的provided一样的。 |
runtimeOnly | apk | module和它的使用者,运行时可用.它跟过时的apk是一样. |
3、使用annotationProcessor
我的项目使用的注解插件是android-apt。
什么是APT?
APT(Annotation Processing Tool)是一种处理注释的工具,它对源代码文件进行检测找出其中的Annotation,使用Annotation进行额外的处理。 Annotation处理器在处理Annotation时可以根据源文件中的Annotation生成额外的源文件和其它的文件(文件具体内容由Annotation处理器的编写者决定),APT还会编译生成的源文件和原来的源文件,将它们一起生成class文件。
Android Gradle 插件提供了名为 annotationProcessor 的功能来完全代替 android-apt ,自此android-apt 作者在官网发表声明证实了后续将不会继续维护 android-apt ,并推荐大家使用 Android 官方插件annotationProcessor。
切换步骤:
1.)修改Project 的build.gradle配置
android-apt方式
dependencies {
classpath 'com.android.tools.build:gradle:2.2.3'
classpath 'com.neenbedankt.gradle.plugins:android-apt:1.8'
}
修改后
annotationProcessor
方式
dependencies {
classpath 'com.android.tools.build:gradle:3.0.0'
}
android-apt方式
buildscript {
repositories {
jcenter()
}
dependencies {
classpath 'com.neenbedankt.gradle.plugins:android-apt:1.8'
}
}
apply plugin: 'com.neenbedankt.android-apt'
dependencies {
compile 'org.greenrobot:eventbus:3.0.0'
apt'org.greenrobot:eventbus-annotation-processor:3.0.1'//apt
}
修改后
annotationProcessor
方式,只保留dependencies 里面的引用并且把apt 换成annotationProcessor就可以了
dependencies {
compile 'org.greenrobot:eventbus:3.0.0'
annotationProcessor 'org.greenrobot:eventbus-annotation-processor:3.0.1'
}
其他编译错误
1、The specified Android SDK Build Tools version (23.0.1) is ignored, as it is below the minimum supported version (26.0.2) for Android Gradle Plugin 3.0.0. Android SDK Build Tools 26.0.2 will be used. To suppress this warning, remove "buildToolsVersion '23.0.1'" from your build.gradle file, as each version of the Android Gradle Plugin now has a default version of the build tools. Update Build Tools version and sync project Open File
Gradle Plugin 3.0.0要求buildToolsVersion的最低版本是26.0.2
2、Error:org.gradle.process.internal.ExecException: Process 'command '/Users/chenlin/work/Android/android-sdks/build-tools/26.0.2/aapt'' finished with non-zero exit value 1
在gradle.properties中关闭APPT2编译 : android.enableAapt2=false
3、gradle打包,自定义apk名称代码报错(Cannot set the value of read-only property ‘outputFile’ )
Error:(56, 0) Cannot set the value of read-only property ‘outputFile’ for ApkVariantOutputImpl_Decorated{apkData=Main{type=MAIN, fullName=debug, filters=[]}} of type com.android.build.gradle.internal.api.ApkVariantOutputImpl.
在app的buide.gradle修改3.0之前输出自定义apk名字的代码,代码如下:
// applicationVariants.all { variant ->
// variant.outputs.each { output ->
// def outputFile = output.outputFile
// if (outputFile != null && outputFile.name.endsWith('.apk')) {
// // 输出apk名称为1hu_v1.0_wandoujia.apk
// def fileName = "1hu_${defaultConfig.versionName}_${variant.productFlavors[0].name}.apk"
// output.outputFile = new File(outputFile.parent, fileName)
// }
// }
// }
修改为:
android.applicationVariants.all { variant ->
variant.outputs.all {
outputFileName = "1hu_${defaultConfig.versionName}_${variant.productFlavors[0].name}.apk"
}
}
4、
Error:Cannot choose between the following configurations of project :Hud:
- debugApiElements
- debugRuntimeElements
- releaseApiElements
- releaseRuntimeElements
All of them match the consumer attributes:
- Configuration 'debugApiElements':
- Found com.android.build.api.attributes.BuildTypeAttr 'debug' but wasn't required.
- Found com.android.build.gradle.internal.dependency.AndroidTypeAttr 'Aar' but wasn't required.
- Found com.android.build.gradle.internal.dependency.VariantAttr 'debug' but wasn't required.
- Found org.gradle.api.attributes.Usage 'java-api' but wasn't required.
- Configuration 'debugRuntimeElements':
- Found com.android.build.api.attributes.BuildTypeAttr 'debug' but wasn't required.
- Found com.android.build.gradle.internal.dependency.AndroidTypeAttr 'Aar' but wasn't required.
- Found com.android.build.gradle.internal.dependency.VariantAttr 'debug' but wasn't required.
- Found org.gradle.api.attributes.Usage 'java-runtime' but wasn't required.
- Configuration 'releaseApiElements':
- Found com.android.build.api.attributes.BuildTypeAttr 'release' but wasn't required.
- Found com.android.build.gradle.internal.dependency.AndroidTypeAttr 'Aar' but wasn't required.
- Found com.android.build.gradle.internal.dependency.VariantAttr 'release' but wasn't required.
- Found org.gradle.api.attributes.Usage 'java-api' but wasn't required.
- Configuration 'releaseRuntimeElements':
- Found com.android.build.api.attributes.BuildTypeAttr 'release' but wasn't required.
- Found com.android.build.gradle.internal.dependency.AndroidTypeAttr 'Aar' but wasn't required.
- Found com.android.build.gradle.internal.dependency.VariantAttr 'release' but wasn't required.
- Found org.gradle.api.attributes.Usage 'java-runtime' but wasn't required.
把gradle配置中的 compile project(':xxx')改成implementation project(':xxx')
5、找不到KeyEventCompat类
v4包升级到了27.0.0,我项目中用它的hasNoModifiers等方法来做的ViewPager的懒加载,找不到KeyEventCompat类,而25.3.1版的v4包中此类是存在的。最后查看源码,发现这个hasNoModifiers方法已经被KeyEvent实现了。
贴出解决此处修改的用于实现ViewPager懒加载方法的部分代码
public boolean executeKeyEvent(KeyEvent event) {
boolean handled = false;
if (event.getAction() == KeyEvent.ACTION_DOWN) {
switch (event.getKeyCode()) {
case KeyEvent.KEYCODE_DPAD_LEFT:
handled = arrowScroll(FOCUS_LEFT);
break;
case KeyEvent.KEYCODE_DPAD_RIGHT:
handled = arrowScroll(FOCUS_RIGHT);
break;
case KeyEvent.KEYCODE_TAB:
if (Build.VERSION.SDK_INT >= 11) {
// if (KeyEventCompat.hasNoModifiers(event)) {
if (event.hasNoModifiers()) {
handled = arrowScroll(FOCUS_FORWARD);
// } else if (KeyEventCompat.hasModifiers(event, KeyEvent.META_SHIFT_ON)) {
} else if (event.hasModifiers(KeyEvent.META_SHIFT_ON)) {
handled = arrowScroll(FOCUS_BACKWARD);
}
}
break;
}
}
return handled;
}