十年匠心定制 · 商业建站与技术教学双线并行 咨询热线:400-886-1026 service@lmnt.cn
ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

Android Studio打包APK卡在assembleDebug?Gradle构建卡顿的完整排查与解决

Android Studio打包APK卡在assembleDebug?Gradle构建卡顿的完整排查与解决 用Android Studio打包APK最让人头疼的瞬间就是点下Run或者Build之后进度条停在Running Gradle task assembleDebug...这一行十分钟、二十分钟、甚至半小时都不动弹。尤其是头一回接触安卓开发的新手遇到这个卡死现场第一反应基本是“是不是我电脑坏了”或者“Android Studio是不是死掉了”。其实这个问题非常典型背后原因说复杂很复杂说简单也简单——绝大多数情况不是代码问题而是Gradle构建环境和网络依赖的问题。这篇文章我就用实际踩坑的经验把这件“卡住”的破事彻底拆开Gradle执行assembleDebug到底在干什么为什么会卡以及从环境版本、依赖镜像、内存配置、日志排查这几个角度怎么一步步定位和解决。不管你是刚装好Android Studio的学生还是从Eclipse转过来的老开发这篇文章都能让你少走不少弯路。1. 为什么卡在assembleDebug先弄清Gradle在做什么1.1 assembleDebug这个任务到底在干嘛先说结论assembleDebug不是“一键导出APK”它是一个Gradle任务链的汇总入口。当你点击Run按钮时Android Studio会调用Gradle执行这个任务它会串联起以下工作读取项目根目录下的build.gradle、settings.gradle、gradle.properties等配置文件解析依赖关系检查并下载项目声明的所有第三方库androidx、gson、okhttp等等这些库可能来自Google仓库、Maven Central或JitPack执行代码编译Java/Kotlin源码变成class文件调用D8/R8把class打包成dex文件处理资源文件生成R.java把res目录里的布局、图片、字符串打包最后把所有产物打包成未签名的APK同时还会生成debug签名。每一步都有可能成为卡住的地方。但据我观察真实场景里九成以上的卡死都发生在“依赖下载”或者“Gradle本身下载”这一步而不是代码编译本身。原因很简单代码编译是CPU密集型任务再慢也有进度但网络下载是阻塞型任务一旦网络拉胯、镜像地址不通、或者Gradle长时间等待某个仓库的响应进度条就会无限期卡住甚至不报任何错误。1.2 卡住的不同形态是“假死”还是“真死”这个我得先说清楚因为很多同学一看进度条不动就直接强杀进程导致下一次构建又从头来过。形态一状态栏一直转圈Build窗口没有输出。这种大概率是在下载Gradle发行版或依赖库网络延迟大或者被墙了。形态二Build窗口疯狂输出日志但进度条卡在某个Task上。这种往往是某个依赖正在超时重试或者是Gradle Daemon内存不足导致GC频繁。形态三日志停在“Caching disabled”之类的话然后没有任何输出。这种多见于Gradle 7.0以上版本和Android Studio版本不匹配任务执行到一半静默失败。我的建议是先别急着杀进程先打开Build窗口看日志。如果日志还在滚动说明Gradle还活着再多等两分钟。如果日志十分钟没有任何新增再看接下来的章节逐项排查。2. 环境体检版本匹配才是第一道门槛2.1 JDK、AGP、Gradle三者的版本对应关系很多卡在assembleDebug的问题换个角度看其实是版本不兼容。Android Studio每个版本都内置了一个JBRJetBrains Runtime基于JDK的定制版同时AGPAndroid Gradle Plugin对Gradle版本有最低要求Gradle版本又对JDK版本有要求。三者只要有一个对不上Gradle就会在初始化阶段出问题表现就是构建卡住、报错、反复同步。我整理了一个常见的对应表基于官方兼容矩阵Android Studio版本AGP版本Gradle最低版本推荐JDK版本Dolphin 2021.3.17.0.07.0.2JDK 11Electric Eel 2022.1.17.4.07.5JDK 11Flamingo 2022.2.18.0.08.0JDK 17Hedgehog 2023.1.18.2.08.2JDK 17Iguana 2023.2.18.3.08.4JDK 17注意这里的Gradle版本不是你在Android Studio里“项目结构”里随便选的而是项目里gradle/wrapper/gradle-wrapper.properties文件中distributionUrl指定的版本。提示如果你从网上下载了一个老项目或者从GitHub克隆了别人三年前的项目AGP还是4.x、Gradle还是6.x而你用的是新版的Android Studio那构建卡住几乎是必然的。你可以在项目的build.gradle文件里看到AGP版本声明然后在gradle-wrapper.properties里确认Gradle版本。2.2 确定当前项目实际使用的Gradle版本具体操作路径打开项目后左侧文件树里找到gradle/wrapper/gradle-wrapper.properties打开内容类似这样distributionBaseGRADLE_USER_HOME distributionPathwrapper/dists distributionUrlhttps\://services.gradle.org/distributions/gradle-8.7-bin.zip zipStoreBaseGRADLE_USER_HOME zipStorePathwrapper/distsdistributionUrl就是Gradle要下载的发行版地址。如果你看到gradle-8.7-bin.zipGradle就会在第一次构建时去services.gradle.org下载这个包。官方服务器在国内访问其实很不稳定慢、断连、超时都是常态很多人第一次构建卡住就是卡在这个地方——其实Gradle发行版还没下载完。这里有个细节gradle-wrapper.jar和gradle-wrapper.properties决定了Gradle版本。Android Studio的“Sync Now”本质上就是调用wrapper去解析并下载对应版本的Gradle然后才进入项目配置阶段。2.3 Android Studio首次运行与SDK组件缺失还有一种场景是全新安装Android Studio首次创建项目后构建卡在assembleDebug前。原因是SDK平台组件没装全。Android Studio本身是一个IDE但是构建APK需要Android SDK Platform、Build-Tools、Platform-Tools这些东西。如果首次启动时没有通过SDK Manager把这些组件下载好Gradle构建时就会触发SDK自动下载同样走的是Google的服务器网络差的话就会卡住。排查方式点击Android Studio右上角的SDK Manager或者菜单 Tools - SDK Manager检查是否安装了Android SDK Platform对应你项目compileSdk的版本比如API 34Android SDK Build-ToolsAGP有默认版本要求SDK Platform-Toolsadb等工具。如果没有先把这些装上再回来跑构建。3. 依赖下载卡住最典型的卡死现场3.1 国内镜像配置阿里云/腾讯云仓库假设你的Gradle版本没问题SDK也装齐了但构建还是卡住接下来就要考虑依赖仓库的访问速度问题。Gradle默认的仓库声明一般是repositories { google() mavenCentral() }google()指向https://dl.google.com/dl/android/maven2/mavenCentral()指向https://repo.maven.apache.org/maven2/。这两个仓库在国内的访问速度和稳定性谁用谁知道时不时的超时就是进度条卡住的原因。解决办法是把仓库镜像换成国内地址。这里提供阿里云和腾讯云的两套配置我实测下来稳定性和速度都能接受。在项目根目录的settings.gradle文件里新版Gradle推荐这么写把pluginManagement和dependencyResolutionManagement两块都换成镜像地址pluginManagement { repositories { // 阿里云镜像 maven { url https://maven.aliyun.com/repository/google } maven { url https://maven.aliyun.com/repository/gradle-plugin } maven { url https://maven.aliyun.com/repository/public } // 腾讯云镜像二选一即可也可以都保留 maven { url https://mirrors.cloud.tencent.com/nexus/repository/maven-public/ } google() mavenCentral() } } dependencyResolutionManagement { repositoriesMode.set(RepositoriesMode.FAIL_ON_PROJECT_REPOS) repositories { maven { url https://maven.aliyun.com/repository/google } maven { url https://maven.aliyun.com/repository/public } google() mavenCentral() } }有几个点需要解释一下为什么镜像仓库和google()、mavenCentral()一起保留因为某些冷门依赖在镜像仓库里可能没有完全同步保留官方仓库作为兜底避免“镜像仓库找不到依赖”的情况。FAIL_ON_PROJECT_REPOS的意思是禁止在模块级build.gradle里单独声明仓库统一走根目录配置。如果你项目里某个模块自己声明了仓库可能会报错把它改成PREFER_SETTINGS或者去掉这一行即可。如果你用的是老项目仓库配置在根目录build.gradle的allprojects { repositories { ... } }里同样把镜像地址加进去即可。注意修改完仓库配置后一定要执行一次 “File - Sync Project with Gradle Files” 或者点击工具栏的大象图标重新同步否则新配置不生效。3.2 配置Gradle Distribution下载加速仓库镜像解决的是依赖库下载问题还有一个更早的环节需要处理Gradle发行版本身。前面提到第一次构建时wapper会去services.gradle.org下载Gradle压缩包如果这一步就卡住后面所有操作都无从谈起。解决方案有两种第一种直接改distributionUrl为国内镜像地址。腾讯云、阿里云都提供了Gradle发行版的镜像比如腾讯云的地址格式是distributionUrlhttps\://mirrors.cloud.tencent.com/gradle/gradle-8.7-bin.zip这样wrapper会从腾讯云下载速度快很多。第二种手动下载Gradle压缩包放到本地Gradle缓存目录。Gradle的缓存路径默认在用户目录下的.gradle/wrapper/dists。你可以按照gradle-8.7-bin/一串随机字符这样的目录结构把下载好的zip放进去。不过这个目录结构有点随机新手容易放错我建议先直接改镜像地址基本上就不需要手动放包了。顺便提一下热词里经常出现的“gradle离线包”其实就是这个Gradle发行版zip。如果你单位内网不能访问外网可以在一台能联网的电脑上下载好对应版本的zip拷贝到内网机器上解压到指定目录也能让构建不再卡住。具体目录规则是Windows: C:\Users\你的用户名\.gradle\wrapper\dists\gradle-8.7-bin\随机hash\ Linux/macOS: ~/.gradle/wrapper/dists/gradle-8.7-bin/随机hash\把zip解压后的内容放在这个目录里Gradle就会认为已经下载过了直接使用。3.3 让构建输出更透明开启详细日志其实很多卡住的问题只要你能看到Gradle在干什么就成功了一半。默认状态下Android Studio的Build窗口只显示Task级进度看不到具体下载的是哪个依赖。如果想让日志更详细可以在gradle.properties末尾加一句org.gradle.logging.levelinfo或者运行时加上--info参数点击Run旁边的下拉箭头选择“Edit Configurations”在“Arguments”里填--info。之后构建时Build窗口会输出每个依赖的下载地址、连接状态、超时信息。这样你就知道是卡在dl.google.com还是卡在plugins.gradle.org对症下药。更极端的调试方式是--stacktrace配合--debug不过日志量巨大一般用不上--debug--info已经足够定位绝大多数网络卡顿问题。4. 构建过程卡住内存、守护进程与任务裁剪4.1 给Gradle分配合理的内存如果依赖都下载好了网络也没问题但构建还是慢得离谱、甚至像卡死一样那就要考虑Gradle运行时的内存配置。Gradle默认运行在JVM上Android Studio安装时允许你配置Gradle VM堆大小。打开Android Studio顶部菜单 Help - Change Memory Settings能看到IDE本身的内存配置。而Gradle构建进程的内存则要在项目根目录gradle.properties里配置org.gradle.jvmargs-Xmx2048m -XX:MaxMetaspaceSize512m -XX:HeapDumpOnOutOfMemoryError这个-Xmx就是Gradle JVM能使用的最大堆内存。如果是老电脑或者内存本来就紧张设太大会导致系统频繁交换内存构建反而卡。如果设太小比如默认的512m或768m碰到大项目时Gradle会频繁触发GC甚至OOM表现就是进度条长时间卡在某个Task上CPU占用却忽高忽低。我个人的经验值小于8GB内存的机器给-Xmx设置 1536m 到 2048m 之间16GB内存的机器可以给 3072m 到 4096m要是项目特别大多个模块、依赖很多还得再加。同时建议把下面这一行也加上org.gradle.paralleltrue org.gradle.cachingtrue并行构建能同时跑多个模块任务构建缓存能跳过未变化的Task这两个对缩短构建时间非常有效。不过要注意org.gradle.paralleltrue对老版本Gradle兼容性一般如果你用的是Gradle 6.x建议先只加缓存确认稳定后再开并行。4.2 处理Gradle Daemon与并发问题Gradle默认会启动一个守护进程Daemon来常驻内存复用构建结果。但Daemon也有翻车的时候内存泄漏、端口冲突、缓存损坏都会让构建卡住。有一种经典场景卡在assembleDebug但是换一台电脑相同代码很快就过了。这时候大概率是你本地Daemon出了问题。解决办法很简单在终端执行./gradlew --stopWindows用gradlew.bat --stop停掉所有Daemon进程找到用户目录下的.gradle/caches缓存目录删掉里面modules-2或者整个caches目录注意这会清空所有本地依赖缓存下次构建需要重新下载重启Android Studio重新同步项目。另外如果你电脑上开着Android模拟器、Docker、多个IDEA实例同时还在跑构建内存也会吃紧。Gradle构建的时候尽量关掉不必要的应用尤其是浏览器开几十个标签页这种操作还是忍一忍吧。4.3 跳过不必要的任务缩短构建时间有些项目的build.gradle里配置了自定义任务比如lint检查、单元测试等这些任务在assembleDebug时不一定必须执行。如果它们卡住了比如lint下载某个工具整个构建就会跟着卡住。优化方式点Run构建时方法一直接在命令行执行gradlew assembleDebug -x lint -x test跳过lint和测试任务方法二在模块的build.gradle里配置android { lintOptions { checkReleaseBuilds false abortOnError false } }注意lintOptions被标记为废弃了新版AGP改用lint { checkReleaseBuilds false }但旧项目里用lintOptions还能兼容看你的AGP版本决定。我个人建议是日常开发调试就只打Debug包别在开发中反复触发Release构建。Release包的压缩、混淆、还有各种资源收缩时间比Debug多出好几倍卡住的概率也更高。5. 问题排查与错误日志速查实录5.1 卡死现场如何定位遇到卡住时我会按下面的顺序排查一步到位不浪费感情第一步看Build窗口日志。如果日志停在Download、Resolve、Wait这几个词那是网络问题去检查镜像配置和DNS。如果日志停在某个Task名称比如:app:mergeDebugResources那是资源处理或内存问题去查内存配置。第二步打开任务管理器Windows/活动监视器macOS看Java进程的CPU和内存如果Java进程CPU占用接近100%说明在干活只是慢先等着如果CPU是0而内存很高说明Gradle在GC或者等网络大概率有问题。第三步看Gradle缓存目录的大小。如果用户目录.gradle/caches一直在涨说明还在下载耐心等如果好几分钟都不涨那就是连接断开了杀掉构建重新来。遇到那种“等了半小时还在原地”的情况不用犹豫直接再次./gradlew assembleDebug --info走一遍结合日志基本能锁定问题点。5.2 常见错误与日志对照表这里整理一份高频出现但容易误判的报错情况日志关键词实际问题推荐解法Could not resolve all files for configuration某个依赖下载失败检查仓库镜像配置确认依赖是否存在于镜像中Could not HEAD / xxx访问仓库失败谷歌仓库不通换阿里云/腾讯云镜像Failed to notify dependency resolution listener仓库列表中有不可访问的远端清理仓库配置把不可用的地址移除Timeout waiting to lock buildSrc多个Gradle进程锁冲突杀掉所有Java进程删.gradle下的lock文件java.lang.OutOfMemoryErrorGradle堆内存不足调大org.gradle.jvmargs的-XmxGradle task assembleDebug failed with exit code 1编译或资源错误看Build窗口具体报错代码不是所有卡住都是网络Unable to load class org.gradle.api.attributes.AttributeContainerGradle版本和AGP不匹配按版本对应表升级或降级GradleCould not find com.android.tools.build:gradle:x.x.xAGP版本在仓库中不存在改镜像源并确认AGP版本号正确有一条经验要特别注意看到 “Could not download” 或 “Could not resolve” 时先确认错误里提到的仓库地址再动手改配置。很多人一看到下载失败就加“阿里云镜像”结果问题出在某个私有仓库上改了也没用浪费半天时间。5.3 兜底方案删除缓存、重新同步如果上面所有方法都试过构建还是卡在同一个位置那就走最后的大招删除本地所有Gradle缓存和构建产物强制从零开始构建。这个操作要慎重它相当于把Gradle的“记忆”全部清空所有依赖需要重新下载。不过在国内镜像配置好的前提下也就是几分钟的事。具体步骤如下关闭Android Studio中的所有项目打开文件管理器定位到用户目录下的.gradle文件夹删除里面caches和wrapper/dists两个子目录相当于完全清空依赖缓存和Gradle发行版缓存回到项目目录删除.gradle文件夹项目级缓存、删除app/build目录构建产物重新打开Android Studio让Gradle重新下载所有依赖并构建。注意如果你曾经给不同的项目配置过不同版本的Gradle删除wrapper/dists后下次每个项目第一次构建都会重新下载对应版本的Gradle占用带宽和时间这也是必须付出的代价。6. 按场景操作的完整配置参考6.1 新项目模板的推荐配置如果你是新建项目就卡住可以按这个配置来一遍第一步检查gradle-wrapper.properties把Gradle版本镜像改到腾讯云distributionUrlhttps\://mirrors.cloud.tencent.com/gradle/gradle-8.7-bin.zip第二步修改settings.gradle加入阿里云镜像仓库pluginManagement { repositories { maven { url https://maven.aliyun.com/repository/google } maven { url https://maven.aliyun.com/repository/gradle-plugin } maven { url https://maven.aliyun.com/repository/public } google() mavenCentral() } } dependencyResolutionManagement { repositoriesMode.set(RepositoriesMode.FAIL_ON_PROJECT_REPOS) repositories { maven { url https://maven.aliyun.com/repository/google } maven { url https://maven.aliyun.com/repository/public } google() mavenCentral() } }第三步修改gradle.properties至少加上这几行org.gradle.jvmargs-Xmx2048m -XX:MaxMetaspaceSize512m -XX:HeapDumpOnOutOfMemoryError org.gradle.cachingtrue org.gradle.paralleltrue org.gradle.daemontrue然后再次同步项目跑构建绝大多数新建项目卡住的问题都能解决。6.2 老项目的移植场景热词里有一条“移植android studio项目”这个场景我也简单说两句。从网上下载老项目后第一件事不是点Run而是先做三件事检查AGP版本和Gradle版本确认它们与当前Android Studio兼容。老项目AGP版本过低比如3.x而新AS自带JDK 17直接构建大概率卡住或报错把依赖仓库统一替换为国内镜像检查项目的compileSdk、minSdk、targetSdk是否已安装对应SDK平台没有就装好。移植项目卡住的坑多半不是代码问题而是这三件事没做。把这三步过一遍比在报错日志里反复研究效率高得多。6.3 关于Flutter项目的补充说明热词里还有“you are applying flutters main gradle plugin imperatively using the apply s”这个和Flutter打包APK卡住相关补充一句。Flutter项目底层也是通过Android Gradle插件构建APK如果你在Flutter项目里遇到assembleDebug卡住核心思路一致检查android/settings.gradle、android/build.gradle里的仓库地址加入阿里云镜像同时Gradle发行版下载地址也是同样的改法。新版Flutter模板默认使用dev.flutter:flutter-gradle-plugin如果报错提到“imperatively using the apply”通常是把老版本Flutter里的Gradle配置直接挪到新项目导致的建议按Flutter官方的最新模板重建项目别硬改。个人实操体会说实话我自己刚入行那会第一次建项目就卡在assembleDebug上整整折腾了一个下午最后发现根本不是镜像的问题而是Gradle发行版压缩包下载到一半断了重新下载一次就过了。从那以后我养成了两个习惯写在这里供你参考。第一个习惯是先改镜像再建项目。新建项目或者克隆项目后第一件事就是把gradle-wrapper.properties里的下载地址换到腾讯云然后在settings.gradle里配好阿里云仓库。虽然第一次构建多花两分钟但换来的是后续所有项目构建的稳定值。第二个习惯是日志永远开--info。默认的构建日志太“优雅”了很多卡住的原因被吞掉了开--info之后Gradle 具体在等哪个依赖、连哪个仓库全都能看到定位问题快得不是一星半点。希望这篇经验总结能帮你少走一些弯路。如果你按这个思路排查完还是卡在某个地方可以把--info日志的最后二十行贴出来找找看问题多半就藏在那里面。
返回列表