以下内容均为个人理解,如果有描述不正确的地方,欢迎指正 转载请注明原文链接
开始填坑之前,先简单聊聊 gradle,Gradle 其实就是一个构建项目的工具,也就是把那一个个文件、文件夹按照一定的规则关联起来,形成一个项目的工具,它其实不仅仅是用在 AndroidStudio 上。
我们在 AS 中用到的 Gradle 其实应该被叫做 Android Gradle Plugin,也就是安卓项目上的 gradle 插件;
Gradle 插件会有版本号,每个版本号又对应有一个或一些 Gradle 发行版本(一般是限定一个最低版本),也就是我们常见的类似 gradle-3.1-all.zip 这种东西;
如果这两个版本对应不上了,那你的工程构建的时候就会报错。
对应关系如下(参考自 developer.android.google.cn ):
插件版本 | 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+ |
Android Studio 3.0 之后自动将插件版本升级到 3.0.0,所以我们也需要对应地把 Gradle 升级到 4.1 才行
另外, Android Gradle Plugin 又会跟 Android SDK BuildTool 有关联,因为它还承接着 AndroidStudio 里的编译相关的功能,这也是我们要在项目的 local.properties 文件里写明 Android SDK 路径、在 build.gradle 里注明 buildToolsVersion 的原因。
所以 Android Gradle Plugin 本质上就是 一个 AS 的插件,它一边调用 Gradle 本身的代码和批处理工具来构建项目,一边调用 Android SDK 的编译、打包功能,从而让我们能够顺畅地在 AS 上进行开发。
- dependencies {
- classpath 'com.android.tools.build:gradle:3.0.1' //这里从2.2.2改到了3.0.1
- }
然后同步 gradle。 通常情况下你会发现速度特别慢,因为没有翻墙,默认是从国外服务器下载 gradle; 这时候就可以强关 AS,直接在网上找资源,把 gradle-4.1-all.zip 这个包,放在
- distributionUrl=https\://services.gradle.org/distributions/gradle-4.1-all.zip //这里从 3.1 改到了 4.1
C:\Users \ 你的用户名. gradle\wrapper\dists\gradle-4.1-all\bzyivzo6n839fup2jbap0tjew目录中(最后那个乱码文件夹名字每台机器上不一样),注意不需要手动解压,然后重启 AS 自动同步 gradle 即可;
- repositories {
- mavenCentral()
- jcenter()
- //加上下面这段
- maven {
- url 'https://maven.google.com/'
- name 'Google'
- }
- }
这个提示,说是需要去掉各个 module 的 build.gradle 中的 buildToolsVersion 的设置,因为 3.0.1 以上的 gradle 插件会自动用一个默认的 BuildTool 版本,不需要像以前一样,在每个 build.gradle 里写明 buildToolsVersion 了。 所以我们把提示到的各个 build.gradle 中的这行删掉,再重新同步一下 gradle,就不会报这个错了。
- Error: The specified Android SDK Build Tools version(25.0.0) is ignored,
- as it is below the minimum supported version(26.0.2) for Android Gradle Plugin 3.0.1.Android SDK Build Tools 26.0.2 will be used.To suppress this warning,
- remove "buildToolsVersion '25.0.0'"from your build.gradle file,
- as each version of the Android Gradle Plugin now has a
- default version of the build tools.
需要在 app/build.gradle 加上默认的 dimension;大概就是为了保证各个渠道包要保持某些属性的一致;总之按照官网上的说法,只要给每个渠道都设置一个 "flavorDimensions" 就可以了,代码如下(app/build.gradle)
- Error:All flavors must now belong to a named flavor dimension. Learn more at https://d.android.com/r/tools/flavorDimensions-missing-error-message.html
- flavorDimensions "default" //这个名字貌似随便取,也可以有多个,总之一定要有..
- productFlavors {
- market {
- dimension "default"
- }
- // other{
- // dimension "default" //如果有其他的渠道,也要做类似的声明
- // }
- }
一时半会儿不知道怎么搞,看看这个开发者文档链接的说明吧, developer.android.com 这个域名不翻墙是进不去的,不过现在已经有了国内的域名,把域名替换成 developer.android.google.cn,后面保持不变就可以访问了;其他类似的官方文档地址也一样可以用这个方法去访问。 看了下官方文档,大意是在说,工程里的某个 module 依赖了某个 jar 包, 然后 jar 里面又用到了注解,在新的 gradle 版本里,需要写新的 groovy 代码来对每个引用注解的地方单独配置。在以往的版本中,gradle 会默认给每个 module 都依赖一个 annotationProcess,导致很多多余的对 annotationProcess 的依赖,老版本中的默认方法,会在将来版本中被删除。 按照提示, 解决方案大致有两个: 要么我们需要在依赖于注解的 module 中,加上 "annotationProcessor" 这个配置; 要么我们可以设置 android.defaultConfig.javaCompileOptions.annotationProcessorOptions.includeCompileClasspath = true,但是要注意这玩法以后会被删除 按照官方推荐的第一种方法:应该是在报错的 build.gradle 中修改:
- Error:Execution failed for task ':framework:third:xxxModule:javaPreCompileDebug'.
- Annotation processors must be explicitly declared now.
- The following dependencies on the compile classpath are found to contain annotation processor.
- Please add them to the annotationProcessor configuration.
- xxxxxx.jar (com.xxxx:xxxxx:1.0.5)
- Alternatively, set android.defaultConfig.javaCompileOptions.annotationProcessorOptions.includeCompileClasspath = true to continue with previous behavior.
- Note that this option is deprecated and will be removed in the future.
- See https://developer.android.com/r/tools/annotation-processor-error-message.html for more details.
但是我加上了并没有什么作用,原因待查.. 为了节约时间,还是先用 includeCompileClasspath=true 的办法凑合下吧,以后真的被删除了再说... 直接在 app/build.gradle(准确的说是每个涉及到注解依赖的 module 的 build.gradle)上加一行
- dependencies {
- compile xxxxx
- ...
- //加上类似这些对于注解处理器的的依赖
- annotationProcessor 'com.xxxx.xxxxx-1.0.0'
- }
然后再次同步 gradle
- defaultConfig {
- minSdkVersion rootProject.ext.android.minSdkVersion
- targetSdkVersion rootProject.ext.android.targetSdkVersion
- versionCode 1
- versionName "1.0"
- testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
- javaCompileOptions {
- annotationProcessorOptions {
- includeCompileClasspath = true //加上这行即可
- }
- }
- }
这才发现其实 clean 是没有用的,真正的问题原因在一堆错误的最后几行
- Error:(713, 5) error: style attribute '@android:attr/windowExitAnimation' not found.
- Error:(713, 5) error: style attribute '@android:attr/windowExitAnimation' not found.
- Error:(713, 5) error: style attribute '@android:attr/windowExitAnimation' not found.
AAPT2 , 貌似就是 aapt 的 2.0 版本? aapt.exe 是 Android SDK 里的一个工具,详情出门左转自己查去.. 直接说解决方案: 在 Project/gradle.properties 中添加 android.enableAapt2=false 再次同步...
- Error:java.util.concurrent.ExecutionException: java.util.concurrent.ExecutionException: com.android.tools.aapt2.Aapt2Exception: AAPT2 error: check logs for details
- Error:java.util.concurrent.ExecutionException: com.android.tools.aapt2.Aapt2Exception: AAPT2 error: check logs for
- com.android.tools.aapt2.Aapt2Exception: AAPT2 error: check logs for details
这个错跟 7 号有点类似,又是新版本 gradle 插件不支持某些方法啦,又要换用新的写法才行啦... 然后最后给你贴一个文档地址自己看去。。 大概就是说:现在不支持 manifestOutputFile 这个方法,要用 processManifest.manifestOutputDirectory() 来替换, 也就是你 app/build.gradle 打包的这一段代码要重新写一下;一般我们都会在 build.gradle 中编写这样的代码,来实现对 Manifest 文件的修改、以及自定义 apk 的输出文件名等。
- Error:(247, 1) Execution failed for task ':app:processMarketDebugManifest'.
- Manifest Tasks does not support the manifestOutputFile property any more, please use the manifestOutputDirectory instead.
- For more information, please check https://developer.android.com/studio/build/gradle-plugin-3-0-0-migration.html
- android.applicationVariants.all { variant ->
- variant.outputs.each { output ->
- output.processManifest.doLast {
- ...
- def manifestFile = output.processManifest.manifestOutputFile; //这里被废弃导致报错
- def apkFileName = "_myapp_${android.defaultConfig.versionCode}_${formatedDate}.apk";
- manifestFile.write(updatedContent, 'UTF-8')
- ...
- }
- }
- }
比如
- Error:(250, 1) Execution failed for task ':app:processMarketDebugManifest'.
- No signature of method: java.lang.String.getText() is applicable for argument types: (java.lang.String) values: [UTF-8]
- Possible solutions: getAt(java.lang.String), getAt(groovy.lang.IntRange), getAt(groovy.lang.Range), getAt(int), getAt(java.util.Collection), getAt(groovy.lang.EmptyRange)
比如
- Error:(251, 1) Execution failed for task ':app:processMarketDebugManifest'.
- No signature of method: java.lang.String.write() is applicable for argument types: (java.lang.String, java.lang.String) values: [H:\GitWorkSpace\DouyutvClient\app\build\intermediates\manifests\full\market\debug/AndroidManifest.xml, ...]
- Possible solutions: wait(), trim(), size(), size(), toSet(), wait(long)
反正就是各种各样的 groovy 语法报错,然而并不懂 groovy 语法,现学现卖改一改 我们工程里是既有动态修改 manifest 文件的需求,也有自定义 apk 名字的功能,
- Error:(258, 1) Execution failed for task ':app:processMarketDebugManifest'.
- Cannot set the value of read-only property 'outputFile' for ApkVariantOutputImpl_Decorated{apkData=Main{type=MAIN, fullName=marketDebug, filters=[]}} of type com.android.build.gradle.internal.api.ApkVariantOutputImpl.
- android.applicationVariants.all {
- variant - >variant.outputs.each {
- output - >output.processManifest.doLast {
- def umengKey = "11111111"
- //取得manifest路径
- String manifestPath = "$manifestOutputDirectory/AndroidManifest.xml"
- //取得manifest的文本内容
- def manifestContent = file(manifestPath).getText('UTF-8')
- //替换UMENG_APPKEY的文本
- manifestContent = manifestContent.replaceAll("\\{\\{UMENG_APPKEY\\}\\}", umengKey)
- //重新把内容写进.xml文件里
- file(manifestPath).write(manifestContent, 'UTF-8')
- }
- }
- variant.outputs.all {
- //定义apk名字
- def formatedDate = new Date().format("yyyyMMddHHmm") def apkFileName = "_myapp_${android.defaultConfig.versionCode}_${formatedDate}.apk";
- outputFileName = apkFileName
- }
- }
谷歌爸爸的文档:
developer.android.google.cn/studio/buil…
附一张图
折腾一下午之后的我. gif来源: https://juejin.im/entry/5a31e280f265da43305e7a42