升级Gradle3.0
业精于勤荒于嬉,行成于思毁于随
Android Gradle 3.0.0插件是一个大版本的升级,对于构建多个module带来了显著的性能提升。但同时也更新了DSL和APIS。
升级Gradle3.0所带来的好处如下:
- 通过细粒度的任务图更好地实现多模块项目的并行性
- Variant-aware dependency management (变体感知的依赖管理)
- 可以使用Gradle的新依赖项配置来限制哪些依赖项将其API泄漏到其他模块:implementation,api,compileOnly和runtimeOnly。从而增加构建速度。
- 使用 per-class dexing 加快增量构建速度。每个类被编译成一个独立的dex文件,并且只有这个类被修改后才会重新编译。
升级步骤
升级Gradle版本。在gradle/wrapper/gradle-wrapper.properties
distributionUrl=https\://services.gradle.org/distributions/gradle-4.4-all.zip
升级Android Gradle Plugin版本。在工程的build.gradle
classpath 'com.android.tools.build:gradle:3.1.3'
新的依赖配置
新配置 | 弃用 | |
---|---|---|
implementation | compile | 在编译时,该模块的依赖不会泄露给其他模块。只有在运行时其他模块才能获取依赖。 |
api | compile | 不论是在编译时,还是在运行时,其他模块都可以获得这个依赖。 |
compileOnly | provided | 依赖项仅在编译时对模块可用,并且在编译或运行时对其消费者不可用。 此配置的行为类似于 provided (现在已弃用)。 |
runtimeOnly | apk | 依赖项仅在运行时对模块及其消费者可用。 此配置的行为类似于 apk (现在已弃用)。 |
升级Gradle3.0问题汇总
此处总结我在升级公共库和项目的gradle版本时,所遇到的问题。
问题一
- Gradle 3.0 API更新较多。例如,PrepareLibraryTask等类被移除掉
解决方式
把移除掉的类全部拿过来,放在本地。将gradle2.3的PrepareLibraryTask挪到本地。
注意问题
- 在gradle2.3中的
PrepareLibraryTask
类中使用@ParallelizableTask
注解。而在gradle3.0中该注解被删除,可以使用WorkerExecutor
API替换。 - 在
PrepareLibraryTask
类中去掉useBuildCache相关代码
问题二
Cannot invoke method doLast() on null object
对这个task做判空操作。
问题三
Error:Unable to resolve dependency for ':app@debug/compileClasspath': Could not resolve project :library
使用变体的依赖关系解决方案,您不再需要使用特定于变体的配置(例如freeDebugImplementation)来获取本地模块依赖关系 – 插件会自动提供配置。
// implementation project(path: ":dcsdk",configuration:'debug')
implementation project(":dcsdk") // 用这种替换
问题四
Resolving configuration ‘provided’ directly is not allowed
解决方案
设置setCanBeResolved(true),刚开始并没有作用。后来发现,主项目是通过jar包的形式加载bytePlugin插件。虽然修改了代码,但是并没有打包到指定位置。将其打包到指定位置,就可以解决此问题。
问题五
java.lang.RuntimeException:com.android.builder.dexing.DexArchiveMergerException:
包重复引用。将bytecodemonitor中的
implementation fileTree(dir: 'libs', include: ['*.jar'])
修改为
compileOnly fileTree(dir: 'libs', include: ['*.jar'])
问题六
Could not resolve all dependencies for configuration ‘:demo:debugAndroidTestCompileClasspath’.
A problem occurred configuring project ‘:sdk’.
ABIs [mips64, armeabi, mips] are not supported for platform. Supported ABIs are [armeabi-v7a, arm64-v8a, x86, x86_64].
解决方案
最新的NDK r17版本,已经去掉了armeabi、mips、mips64的ABI支持。
去掉abiFilters中的armeabi选项
ndk {
abiFilters 'x86', 'x86_64', 'armeabi-v7a', 'arm64-v8a'
}
问题七
Caused by: org.gradle.api.internal.artifacts.ivyservice.DefaultLenientConfiguration$ArtifactResolveException: Could not resolve all files for configuration ':demo:releaseUnitTestRuntimeClasspath'.
at org.gradle.api.internal.artifacts.configurations.DefaultConfiguration.rethrowFailure(DefaultConfiguration.java:918)
at org.gradle.api.internal.artifacts.configurations.DefaultConfiguration.access$1600(DefaultConfiguration.java:116)
at org.gradle.api.internal.artifacts.configurations.DefaultConfiguration$ConfigurationFileCollection.getFiles(DefaultConfiguration.java:892)
at org.gradle.api.internal.artifacts.configurations.DefaultConfiguration.getFiles(DefaultConfiguration.java:404)
at org.gradle.api.internal.artifacts.configurations.DefaultConfiguration_Decorated.getFiles(Unknown Source)
at org.gradle.api.file.FileCollection$getFiles.call(Unknown Source)
at com.netease.tech.analysis.plugin.MobileAnalysisPlugin$_apply_closure2$_closure3.doCall(MobileAnalysisPlugin.groovy:53)
at sun.reflect.GeneratedMethodAccessor607.invoke(Unknown Source)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
at org.codehaus.groovy.reflection.CachedMethod.invoke(CachedMethod.java:93)
at groovy.lang.MetaMethod.doMethodInvoke(MetaMethod.java:325)
at org.codehaus.groovy.runtime.metaclass.ClosureMetaClass.invokeMethod(ClosureMetaClass.java:294)
at groovy.lang.MetaClassImpl.invokeMethod(MetaClassImpl.java:1022)
at groovy.lang.Closure.call(Closure.java:414)
at groovy.lang.Closure.call(Closure.java:430)
at org.codehaus.groovy.runtime.DefaultGroovyMethods.each(DefaultGroovyMethods.java:2040)
at org.codehaus.groovy.runtime.DefaultGroovyMethods.each(DefaultGroovyMethods.java:2025)
at org.codehaus.groovy.runtime.DefaultGroovyMethods.each(DefaultGroovyMethods.java:2078)
at org.codehaus.groovy.runtime.dgm$165.invoke(Unknown Source)
at org.codehaus.groovy.runtime.callsite.PogoMetaMethodSite$PogoMetaMethodSiteNoUnwrapNoCoerce.invoke(PogoMetaMethodSite.java:251)
at org.codehaus.groovy.runtime.callsite.PogoMetaMethodSite.call(PogoMetaMethodSite.java:71)
at org.codehaus.groovy.runtime.callsite.AbstractCallSite.call(AbstractCallSite.java:125)
at com.netease.tech.analysis.plugin.MobileAnalysisPlugin$_apply_closure2.doCall(MobileAnalysisPlugin.groovy:41)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
at org.codehaus.groovy.reflection.CachedMethod.invoke(CachedMethod.java:93)
at groovy.lang.MetaMethod.doMethodInvoke(MetaMethod.java:325)
at org.codehaus.groovy.runtime.metaclass.ClosureMetaClass.invokeMethod(ClosureMetaClass.java:294)
at groovy.lang.MetaClassImpl.invokeMethod(MetaClassImpl.java:1022)
at groovy.lang.Closure.call(Closure.java:414)
at org.gradle.listener.ClosureBackedMethodInvocationDispatch.dispatch(ClosureBackedMethodInvocationDispatch.java:40)
at org.gradle.listener.ClosureBackedMethodInvocationDispatch.dispatch(ClosureBackedMethodInvocationDispatch.java:25)
at org.gradle.internal.event.AbstractBroadcastDispatch.dispatch(AbstractBroadcastDispatch.java:42)
at org.gradle.internal.event.BroadcastDispatch$SingletonDispatch.dispatch(BroadcastDispatch.java:230)
at org.gradle.internal.event.BroadcastDispatch$SingletonDispatch.dispatch(BroadcastDispatch.java:149)
at org.gradle.internal.event.AbstractBroadcastDispatch.dispatch(AbstractBroadcastDispatch.java:58)
at org.gradle.internal.event.BroadcastDispatch$CompositeDispatch.dispatch(BroadcastDispatch.java:324)
at org.gradle.internal.event.BroadcastDispatch$CompositeDispatch.dispatch(BroadcastDispatch.java:234)
at org.gradle.internal.event.ListenerBroadcast.dispatch(ListenerBroadcast.java:140)
at org.gradle.internal.event.ListenerBroadcast.dispatch(ListenerBroadcast.java:37)
at org.gradle.internal.dispatch.ProxyDispatchAdapter$DispatchingInvocationHandler.invoke(ProxyDispatchAdapter.java:93)
at com.sun.proxy.$Proxy27.afterEvaluate(Unknown Source)
at org.gradle.configuration.project.LifecycleProjectEvaluator.notifyAfterEvaluate(LifecycleProjectEvaluator.java:76)
... 85 more
解决方案
问题定位到自定义插件的代码
if (conf.isCanBeResolved()) {
f.addAll(conf.getFiles())
}
当调用conf.getFiles() 方法时,就会报错。报错的信息显示,Could not resolve all files for configuration':demo:releaseUnitTestRuntimeClasspath'
。根据报错信息提示,应该是解析不了releaseUnitTestRuntimeClasspath配置的一些文件。
这个问题困扰了很久,最终临时把这些解析不了的task全部过滤掉,然后就可以正常运行了。
问题八
Error:(94, 5) style attribute '@android:attr/windowExitAnimation' not found
Error:(94, 5) style attribute '@android:attr/windowEnterAnimation' not found
解决方案
移除@,即将
<item name="@android:windowEnterAnimation">@anim/anim_toast_show</item>
<item name="@android:windowExitAnimation">@anim/anim_toast_hide</item>
改为:
<item name="android:windowEnterAnimation">@anim/anim_toast_show</item>
<item name="android:windowExitAnimation">@anim/anim_toast_hide</item>