android-gradle记录
android-gradle记录
前篇
- Gradle 2 用户指南 - https://wiki.jikexueyuan.com/project/gradle-2-user-guide/
自定义任务 Task
- Gradle Task的使用 - https://www.jianshu.com/p/cd1a78dc8346
- Android Gradle 自定义Task 详解 - https://blog.csdn.net/zhaoyanjun6/article/details/76408024
gradle 中定义
| 1 | task mylog() { | 

构建指定任务
以构建 testapp 模块的 Release 版本为例, 也就是 :testapp:assembleRelease 任务. 
命令行方式
| 1 | E:\its_rummy\Rummy_AndroidStudio>gradlew :testapp:assembleRelease | 
gui 方式
在 testapp 模块的 build.gradle 中加入自定义任务, 依赖上 assembleRelease 任务即可.
| 1 | task a_buildApplication() { | 

怎么获取任务名
直接 build 的时候可以看到执行的所有任务
| 1 | > Task :testapp:assembleDebug UP-TO-DATE | 
去掉 任务
比如: 去掉 android 构建 apk 时的 verifyReleaseResources 任务
| 1 | tasks.whenTaskAdded {task -> | 
自定义 插件 Plugin
- Gradle自定义插件实现自定义Task - https://www.jianshu.com/p/1b506e0f8a5b
执行多个命令行
参考: execute multiple commands from task - https://stackoverflow.com/questions/35561014/gradle-execute-multiple-commands-from-task
- 错误姿势 - 1 
 2
 3
 4
 5- task adbRestart(type: Exec) { 
 workingDir "$projectDir"
 commandLine 'cmd', '/c', 'adb kill-server'
 commandLine 'cmd', '/c', 'adb start-server'
 }
- 正确姿势 - 1 
 2
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12- task adbRestart() { 
 doLast {
 exec {
 workingDir "$projectDir"
 commandLine 'cmd', '/c', 'adb kill-server'
 }
 exec {
 workingDir "$projectDir"
 commandLine 'cmd', '/c', 'adb start-server'
 }
 }
 }
执行任务
先 cd 到 build.gradle 所在目录
- 执行单个任务. 命令: - gradle xxx- 1 
 2
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23- E:\its_rummy\Rummy_AndroidStudio\app (master -> origin) 
 $ D:\android-studio-3.4.2\gradle\gradle-5.1.1\bin\gradle a_ItsCopyJar
 > Configure project :app
 --- a_DelTempDir
 --- a_ItsCopyAAR
 --- a_unzip
 --- a_ItsCopyJar
 --- its build
 hello world 111
 > Task :app:lint
 Ran lint on variant release: 41 issues found
 Ran lint on variant debug: 41 issues found
 Wrote HTML report to file:///E:/its_rummy/Rummy_AndroidStudio/app/build/reports/lint-results.html
 Wrote XML report to file:///E:/its_rummy/Rummy_AndroidStudio/app/build/reports/lint-results.xml
 Deprecated Gradle features were used in this build, making it incompatible with Gradle 6.0.
 Use '--warning-mode all' to show the individual deprecation warnings.
 See https://docs.gradle.org/5.1.1/userguide/command_line_interface.html#sec:command_line_warnings
 BUILD SUCCESSFUL in 9s
 54 actionable tasks: 4 executed, 50 up-to-date
- 执行多个任务. 命令: - gradle xxx yyy
gradlew 构建 processDebugManifest 显示 报错信息
模块a 引用 模块b 时, 合并 Manifest 报错, 但是给的信息很有先, 只有 Manifest merger failed with multiple errors
查看具体的信息可以在 项目的根目录 (模块目录的上一级目录) 执行: gradlew processDebugManifest --stacktrace -info, 然后搜索关键之 error, fail 之类的就可以找到错误信息
| 1 | E:\its_rummy\Rummy_AndroidStudio>gradlew processDebugManifest --stacktrace -info | 
参考: Manifest merger failed with multiple errors, see logs问题处理 - https://blog.csdn.net/Picasso_L/article/details/53085299
gradle 中写代码逻辑
- Gradle中的buildScript代码块 - https://www.cnblogs.com/huang0925/p/3940528.html
- Gradle全局变量不在buildscript中的范围内 - https://www.thinbug.com/q/27031587
gradle 在执行脚本时,会优先执行 buildscript 代码块中的内容,然后才会执行剩余的 build 脚本。
所以在 buildscript 块中, 使用外部定义的变量是就会报错, 如:
| 1 | def aaa = {} | 
会报错; Could not get unknown property 'aaa'
执行某个任务
- Gradle高阶-Task执行 - https://juejin.cn/post/6844904016778903560 
- 如果 cd 到项目根目录, 就需要带上模块 - 1 - gradlew :Hello:assembleRelease --stacktrace - 表示执行 Hello 模块的 assembleRelease 任务 - assembleRelease 在 as 中看到的只是 assemble, release 指的是 gradle 中的构建类型, 在任务中拼接起来就是 assembleRelease - 1 
 2
 3
 4
 5
 6
 7- android { 
 buildTypes {
 release {
 
 }
 }
 }
- 如果自定义 构建类型 wilker, 则需要在 所有依赖的工程的 gradle 中都添加这个类型 - 1 
 2
 3
 4
 5
 6
 7- android { 
 buildTypes {
 wilker {
 
 }
 }
 }- 执行任务命令则是 - 1 
 2
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23- gradlew :Hello:assembleWilker --stacktrace 
 ---
 ### 定义全局变量
 - 在 *gradle.properties* 中定义的变量, 可以在项目中的所有模块中使用
 
 ---
 ### 在项目中引入任意目录下的模块
 - 这个引入配置在 *settings.gradle* 中配置, 比如引入 *:apicocos* 模块
 ```json
 include ':apicocos'
 project(':apicocos').projectDir = new File("E:/workspace/cocos/TestAtlas/build/android-001/proj/apicocos")
 
 
- 就可以在该项目中使用该模块的资源 - 1 
 2
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25- dependencies { 
 implementation project(':apicocos')
 }
 ---
 ### 读取命令行参数
 - 参考: 向gradle命令任务传递命令行参数的不同方法 - https://juejin.cn/post/7120878611376111646
 1. 在 gradle 中读取参数
 ```json
 if (project.hasProperty("flagSo11")) {
 println("------------ flagSo11:")
 println(flagSo11)
 }
 if (project.hasProperty("flagSo22")) {
 println("------------ flagSo22:")
 println(flagSo22)
 }
- 命令行中加入参数 - 1 - $ gradlew :MyGame:assembleRelease --stacktrace -PflagSo11=aaa -PflagSo22=bbb - 结果 - 1 
 2
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19- ------------ flagSo11: 
 aaa
 ------------ flagSo22:
 bbb
 ---
 ### 命令行构建 apk
 1. 生成 wrapper
 ```json
 set JAVA_HOME=C:\Users\asd01\Desktop\Java\jdk1.8.0_144
 set ANDROID_SDK_ROOT=C:\Users\asd01\Desktop\android_sdk
 set GRADLE_ROOT=C:\Users\asd01\Desktop\gradle-6.7.1
 
 %GRADLE_ROOT%\bin/gradle wrapper
 
- 执行任务, 也就是构建 apk 等任务 (不能和生成 wrapper 同时执行, 不知道为啥) - 1 
 2
 3
 4
 5- set JAVA_HOME=C:\Users\asd01\Desktop\Java\jdk1.8.0_144 
 set ANDROID_SDK_ROOT=C:\Users\asd01\Desktop\android_sdk
 set GRADLE_ROOT=C:\Users\asd01\Desktop\gradle-6.7.1
 gradlew :launcher:bundleRelease --stacktrace --info- 格式为 :模块名:任务名
 
- 格式为 
- 清楚 - 1 - gradlew clean 
gradle 命令输出日志
- 有两级输出重定向, 第二级才有报错堆栈信息 - 1 - $ gradlew :testapp:assembleRelease --stacktrace > "c:/aaa.txt" 2> "c:/bbb.txt" 
踩坑
maven http 链接不安全
报错: redirect to a secure protocol (like HTTPS)
原因是 gradle 7.0+ 之后, maven 仓库的链接默认要求是 https, 如果是 http, 需要配置安全性字段 allowInsecureProtocol = true
| 1 | buildscript { | 
gradle 插件要求使用 Java 11
报错: Android Gradle plugin requires Java 11 to run. You are currently using Java 1.8
解决办法, 下载 jdk11, 然后修改 as 配置指向 jdk11

gradle 引入错误 material
- 报错: - Can't determine type for tag '<macro name="m3_comp_assist_chip_container_shape">?attr/shapeAppearanceCornerSmall</macro>'
- 解决办法: 将 material 版本降低一点即可 - 1 
 2
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30- implementation 'com.google.android.material:material:1.8.0' 
 // 修改为
 implementation 'com.google.android.material:material:1.0.0'
 ---
 #### 转换 activity 报错
 - 报错: `Failed to transform activity-1.8.0.aar`
 - 解决办法:
 1. 将 项目级 和全局的 gradle.properties 配置里增加 `android.enableJetifier=false`
 2. 引入错误库, 将 `implementation 'androidx.constraintlayout:constraintlayout:2.1.4'`
 ---
 #### 报错: AAPT2
 - 报错: AAPT2 aapt2-4.1.0-6503028-windows Daemon #0: Unexpected error during link, attempting to stop daemon.
 - 解决办法: 项目级 build.gradle 升级 构建工具
 ```json
 dependencies {
 classpath 'com.android.tools.build:gradle:4.2.0'
 classpath 'com.google.gms:google-services:4.3.3'
 }
主题报错
- 报错: java.lang.IllegalStateException: You need to use a Theme.AppCompat theme (or descendant) with this activity.
- 解决办法: 将 AppCompatActivity 修改为 Activity
样式 xml 报错
- 报错 Can’t determine type for tag m3_comp_assist_chip_container_shape shapeAppearanceCornerSmall 错误 
- 解决办法: material 和 constraintlayout 降级 - 1 
 2- implementation 'com.google.android.material:material:1.6.0' 
 implementation 'androidx.constraintlayout:constraintlayout:1.1.3'
创建 handler 报错
- 报错: Can’t create handler inside thread that has not called Looper.prepare() 
- 原因:非主线程中没有开启Looper,而Handler对象必须绑定Looper对象需要调用Looper.prepare()来给线程创建一个消息循环,调用Looper.loop()来使消息循环起作用。 
- 解决办法: 在主线程中创建即可 - 1 
 2
 3
 4- Tools.runOnUiThread(() -> { 
 // 执行代码
 SplashHelper.setIns(new SplashNew());
 });
构建时检查报错找不到 Vendor 类
- 报错: java.lang.NoClassDefFoundError: com/android/tools/lint/client/api/Vendor 
- 解决办法: 加入 lint 禁用配置 - 1 
 2
 3
 4
 5
 6- android { 
 ...
 lintOptions {
 checkReleaseBuilds false
 }
 }