首页 / 资讯中心 / 文章详情

Gradle 7.2 all包实战:老Android工程离线构建与避坑指南

Gradle 7.2 all包实战:老Android工程离线构建与避坑指南 ★ FEATURED ARTICLE
简介gradle-7.2-all.zip 是 Gradle 7.2 版本的完整发行包面向使用 Android Studio 进行 Java 与 Android 项目开发的工程师尤其适合需要离线安装、规避官方源下载缓慢或网络不稳定问题的场景。压缩包整体约 149.73MB内含 Gradle 运行时、库文件及相关工具等完整组件解压后即可在 IDE 中指定本地 Gradle 目录使用。资源在依赖管理、多项目构建、自定义构建逻辑与插件扩展等方面提供支撑Android 插件可完成 APK、AAR 等构建任务帮助开发者稳定编译打包流程。目前已有 1468 人学习下载适合希望减少环境等待、专注项目开发的中级开发者参考使用。1. 一个 7.2 版本的 all 包为什么老项目还在用它如果你手上有个 2020 年前后建起来的 Android 工程gradle-wrapper.properties里大概率写着gradle-7.2-all.zip。这个包不是最新版也不是最稳定版但它卡在一个很微妙的位置上AGP 7.0 到 7.2 能跑JDK 11 能跑Kotlin 1.5 到 1.6 的插件生态也基本齐活。很多团队升级到 7.3 之后发现某些老插件直接报NoSuchMethodError退回来就退到 7.2。所以这个 all 包的实际使用场景不是“新项目起步”而是“存量工程续命”和“离线环境复现”。-all和-bin的区别值得先说清楚。-bin只有运行时二进制-all额外带了源码和文档体积大一圈但 IDE 里点进 Gradle API 能直接看源码排查插件冲突时不用再去翻在线文档。对一线排错来说这个差别很实在。下面按“这个包怎么落地到工程里 → 构建脚本怎么配 → 出问题怎么查”的顺序拆适合正在维护老 Android 工程、或者要在内网机器上把构建跑起来的人。2. 把 all 包接进工程wrapper 配置与离线分发2.1 先判断你该用 wrapper 还是本地安装Gradle 的接入方式有两种选错了后面全是麻烦。第一种是 wrapper工程根目录下有gradle/wrapper/gradle-wrapper.properties和gradlew脚本构建时自动按配置去下载对应版本。第二种是本地安装把 Gradle 解压到某个目录配GRADLE_HOME和PATH用gradle命令直接跑。对团队协作来说wrapper 是唯一正确选择因为它把版本锁在工程里谁拉代码都是同一个 Gradle。本地安装只适合两种场景一是纯命令行临时验证某个版本的行为二是内网机器上先把包准备好再让 wrapper 指向本地文件。我一般会先看工程里有没有gradlew有就一律走 wrapper不去动全局环境避免“我这能跑你那不能跑”的玄学问题。判断当前工程用的哪个版本直接读配置文件# 在工程根目录执行看 distributionUrl 指向哪个版本 cat gradle/wrapper/gradle-wrapper.properties # 如果本机已经装了 gradle也可以看当前命令行用的版本 gradle --versiondistributionUrl这一行是关键形如https\://services.gradle.org/distributions/gradle-7.2-all.zip。注意里面的反斜杠是 properties 文件的转义写法冒号必须转义手改的时候漏了会直接解析失败。2.2 改 distributionUrl 指向本地 all 包离线环境或者下载慢的时候最稳的做法是把gradle-7.2-all.zip放到工程内或内网文件服务上然后改distributionUrl。放在工程内的话建议单独建一个gradle/dist/目录别和 wrapper 的元数据混在一起。# gradle/wrapper/gradle-wrapper.properties distributionBaseGRADLE_USER_HOME distributionPathwrapper/dists # 指向工程内的本地包file 协议路径用相对工程根目录的写法 distributionUrlfile\:///absolute/path/to/gradle-7.2-all.zip zipStoreBaseGRADLE_USER_HOME zipStorePathwrapper/dists这里有个容易翻车的点distributionUrl用file://时路径必须是绝对路径相对路径在部分 Gradle 版本上解析行为不一致。上面写的是绝对路径占位实际替换成你机器上的真实路径。distributionBase和zipStoreBase保持GRADLE_USER_HOME不变解压后的缓存会落在~/.gradle/wrapper/dists/下下次构建直接复用不会重复解压。改完之后跑一次验证# 加 --version 只做版本解析不触发完整构建适合快速验证 wrapper 配置 ./gradlew --version # 输出里应该能看到 Gradle 7.2 和对应的 JVM 版本如果这一步就报Could not resolve或FileNotFoundException先检查路径里的空格和中文file://对这两者很敏感路径带空格时要么转义要么换目录。另一个常见现象是卡在Downloading不动说明distributionUrl还是指向远程地址没改成功。2.3 内网分发的目录约定团队内网分发时我习惯把 all 包和校验文件放一起目录结构固定下来方便脚本化# 内网文件服务上的目录约定示例 # /opt/gradle-dist/ # ├── gradle-7.2-all.zip # ├── gradle-7.2-all.zip.sha256 # └── README.txt # 写明适用 AGP 范围和 JDK 要求 # 生成校验文件分发前做一次接收方落地后核对 sha256sum gradle-7.2-all.zip gradle-7.2-all.zip.sha256 # 接收方核对 sha256sum -c gradle-7.2-all.zip.sha256校验这一步别省。all 包体积不小内网传输中断导致 zip 损坏的情况我见过不止一次表现是解压到一半报zip END header not found然后 wrapper 缓存里留下半截目录后续构建一直失败清缓存才能恢复。先校验再解压能省掉一轮排查。3. 构建脚本适配AGP、JDK 与仓库配置3.1 AGP 版本和 Gradle 7.2 的对应关系Gradle 7.2 能带的 AGP 范围是 7.0.x 到 7.2.x再高的 AGP 会要求 Gradle 7.3 以上。这个对应关系不是建议是硬约束版本对不上时构建直接抛Minimum supported Gradle version is X。工程根目录的build.gradle里插件版本这样写// 根目录 build.gradle用 plugins DSL 声明 AGP 版本 plugins { // 7.2.2 是 7.2 线上比较稳的一个小版本和 Gradle 7.2 配套 id com.android.application version 7.2.2 apply false id com.android.library version 7.2.2 apply false } // 模块级 build.gradle 里只 apply不重复写版本 // plugins { id com.android.application }用pluginsDSL 而不是老的buildscript { classpath }写法好处是版本冲突时错误信息更明确坏处是老工程迁移时容易漏掉settings.gradle里的pluginManagement配置。如果工程还在用buildscript块也不用强行改两种写法在 7.2 上都能跑混用才会出问题。3.2 JDK 版本11 是甜点17 要谨慎Gradle 7.2 官方支持 JDK 8 到 16实际项目里 JDK 11 最稳。JDK 17 在 7.2 上能启动但部分 AGP 内部用的字节码处理库会报Unsupported class file major version 61尤其是开了transform的工程。判断当前用的是哪个 JDK# 看 JAVA_HOME 指向 echo $JAVA_HOME # 看 gradle 实际用的 JVM输出里有一行 JVM: ... ./gradlew --version # 如果 JAVA_HOME 不对临时指定 JDK 11 跑一次 JAVA_HOME/path/to/jdk-11 ./gradlew assembleDebug./gradlew --version输出里的 JVM 行是最可信的因为 Gradle 可能通过org.gradle.java.home覆盖了JAVA_HOME。这个属性写在工程根目录的gradle.properties里# gradle.properties显式锁定构建用的 JDK避免机器环境差异 org.gradle.java.home/path/to/jdk-11 # 并行构建老工程模块多时能明显缩短时间但要注意任务间依赖 org.gradle.paralleltrue # 构建缓存重复构建时省掉大量重复任务 org.gradle.cachingtrueorg.gradle.java.home写死路径的代价是换机器要改团队里我一般只在 CI 配置里写本地开发靠JAVA_HOME控制避免提交后互相覆盖。3.3 仓库配置把 google() 和 mavenCentral() 的顺序理清AGP 7.x 之后google()仓库必须排在mavenCentral()前面否则某些 Android 专属依赖会去中央仓库找找不到再回退构建时间白白拉长。settings.gradle里的dependencyResolutionManagement是 7.x 推荐写法// settings.gradle dependencyResolutionManagement { repositoriesMode.set(RepositoriesMode.FAIL_ON_PROJECT_REPOS) repositories { google() // Android 专属依赖优先 mavenCentral() // 通用依赖兜底 // 内网镜像放最后避免覆盖官方源 maven { url https://your-internal-mirror/repo } } }FAIL_ON_PROJECT_REPOS这个模式值得开它会禁止模块级build.gradle里再声明repositories强制仓库配置集中到一处。老工程迁移时这一项最容易报错因为很多模块里散落着repositories { maven { url ... } }开了这个模式就得逐个清理。清理的收益是依赖解析路径唯一排查“为什么这个依赖版本不对”时不用满工程找仓库声明。4. 避坑与排查五个真实翻车现场4.1 现象构建卡在Downloading gradle-7.2-all.zip不动原因通常是distributionUrl没改成功或者改成了file://但路径写错wrapper 回退到远程地址又连不上。另一种可能是~/.gradle/wrapper/dists/下已经有半截缓存wrapper 认为下载过但校验不过反复重试。解决先cat确认distributionUrl的实际值再清掉对应版本的缓存目录。缓存目录名带哈希直接按版本号找# 找到 7.2 对应的缓存目录并清掉让 wrapper 重新解压 ls ~/.gradle/wrapper/dists/ | grep 7.2 rm -rf ~/.gradle/wrapper/dists/gradle-7.2-all/hash/清完重跑./gradlew --version如果还是卡把--info加上看它到底在请求哪个 URL。4.2 现象Unsupported class file major version 61原因是用 JDK 17 跑了 Gradle 7.2而工程里某个插件或 transform 依赖的字节码处理库不认 Java 17 的 class 文件版本。这个错误不会在配置阶段出现往往在transformDebugClassesWithAsm之类的任务里才炸。解决把构建 JDK 降到 11用org.gradle.java.home或JAVA_HOME锁定。别试图通过--add-opens绕过那是给 JDK 17 跑老 Gradle 用的临时手段7.2 上不适用。4.3 现象Could not find com.android.tools.build:gradle:7.2.2原因是仓库顺序或仓库缺失google()没配或者被内网镜像覆盖了。内网镜像如果只同步了mavenCentral()AGP 这种只在 Google 仓库发布的依赖就找不到。解决确认settings.gradle里google()在镜像之前且镜像没有用exclusiveContent把 Google 仓库的 group 也拦过去。检查镜像配置里有没有对com.android.tools.build这个 group 做排除。4.4 现象Execution failed for task :app:processDebugResources资源报错但文件明明存在原因是 AGP 7.x 开了非传递 R 类non-transitive R class模块间资源引用规则变严老工程里跨模块直接引用R.string.xxx的写法会失效。解决在gradle.properties里临时关掉确认是不是这个原因# 临时关闭非传递 R 类验证问题是否由此引起 android.nonTransitiveRClassfalse确认后不要长期关着正确做法是把跨模块引用改成com.example.module.R的全限定写法或者把共享资源下沉到 base 模块。4.5 现象增量构建失效每次都是全量编译原因是org.gradle.caching开了但缓存目录被清过或者构建脚本里有动态版本号1.0.导致输入不稳定。另一个隐蔽原因是build.gradle里用了System.currentTimeMillis()之类的非确定性输入。解决先看--scan或者--profile报告里哪些任务被判定为 out-of-date再逐个查输入。动态版本号改成固定版本时间戳之类的输入挪到构建外部生成。5. 进阶用 init 脚本统一团队构建环境工程多了之后每个仓库都改一遍gradle.properties不现实。Gradle 的 init 脚本能在构建开始前注入配置适合统一 JDK、仓库和缓存策略。放在~/.gradle/init.d/下对所有工程生效// ~/.gradle/init.d/team-conventions.gradle // 统一注入 JDK 和缓存配置避免每个工程重复写 allprojects { buildscript { repositories { google() mavenCentral() } } repositories { google() mavenCentral() } } // 只对 7.2 版本生效的配置用 gradle.gradleVersion 判断 if (gradle.gradleVersion.startsWith(7.2)) { gradle.settingsEvaluated { settings - // 统一开启构建缓存 settings.buildCache { local { enabled true } } } }init.d脚本的执行时机在settings.gradle之前所以能影响仓库解析。gradle.gradleVersion判断是为了避免脚本在别的版本上误伤团队里有人跑 8.x 工程时不会被这套配置干扰。这个脚本的边界是它不能覆盖工程里显式写的org.gradle.java.home工程级配置优先级更高所以统一 JDK 还得靠 CI 镜像保证。验证 init 脚本是否生效用--info看构建早期的日志或者故意写一个不存在的仓库地址看报错里有没有出现脚本注入的仓库。我一般会在脚本里加一行println team-conventions applied on ${gradle.gradleVersion}构建开头能看到就说明加载了排查时省事。从那以后我每次接手老 Android 工程第一件事就是cat一遍gradle-wrapper.properties和gradle.properties确认版本、JDK、仓库三件事再动手改代码。这三处不对后面写多少业务逻辑都是白搭。希望帮到你。本文还有配套的精品资源点击获取
阅读完成 · 觉得有帮助?
咨询建站