ARTICLE DETAIL

资讯详情

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

Cursor 与 Android Studio 联调时 `R.jar` 删除失败(Windows 文件锁):TaoToken 统一 Key 下的 Gradle 配置骨架与验证动作

Cursor 与 Android Studio 联调时 `R.jar` 删除失败(Windows 文件锁):TaoToken 统一 Key 下的 Gradle 配置骨架与验证动作 1. Windows 下 R.jar 删除失败到底卡在哪如果你在 Windows 上同时开着 Cursor 和 Android Studio 做 Android 联调大概率见过这条日志Unable to delete file: ...\build\intermediates\compile_library_classes_jar\debug\...\R.jar后面跟着「文件被占用」「访问被拒绝」之类的提示。它跟你的业务代码基本没关系纯粹是文件句柄没释放。表现很有迷惑性在 Android Studio 里反复点 Sync、Run 都没用可一旦把 Cursor 关掉再构建就过了。这个现象的本质是 Windows 的文件锁机制——只要有一个进程还持有R.jar的句柄Gradle 的compileDebugJavaWithJavac、compileDebugKotlin这类任务在清理旧产物时就会失败。占用者通常有两类一类是 Gradle Daemon / Worker 残留的java.exe另一类是 Cursor 里 Kotlin 语言服务fwcd.kotlin扩展拉起的java.exe按类路径读取了build目录下的R.jar并长期不放手。前者用gradlew --stop多半能解决后者必须停语言服务或退出 Cursor。这篇就围绕这个场景给你一套可复制的 Gradle 配置骨架、Cursor 的settings.json、以及用 TaoToken 统一 Key 接入 AI 工具后的锁文件定位与验证动作。目标是一次性复现、定位、解除占用而不是每次靠「关 IDE 玄学」。适合正在用 Cursor 写 Android、又用 Android Studio 跑构建的同学。2. 前置用 TaoToken 统一 Key 管住多工具调用在动手排查文件锁之前先把 AI 工具的接入通道理顺。Cursor、Android Studio 里的 AI 插件、以及命令行里的编码 Agent如果各自配一套 Key排查问题时你很难判断是哪个进程在后台跑任务、间接持有构建目录句柄。TaoToken 的思路是给一个统一 Key 和统一 API 通道让这些工具走同一个入口。官网入口在这里https://taotoken.net/?utm_sourcetaotoken_aicg_blog_endutm_mediumcsdnutm_campaignrewriteutm_content API 基址是 https://taotoken.net/api 这个不加 UTM。你需要先在控制台创建 Key地址是 https://taotoken.net/console?utm_sourcetaotoken_aicg_blog_endutm_contentconsoleutm_campaignrewrite Key 管理页在 https://taotoken.net/api-keys?utm_sourcetaotoken_aicg_blog_endutm_contentapi-keysutm_campaignrewrite 。接入文档在 https://taotoken.net/doc?utm_sourcetaotoken_aicg_blog_endutm_contentdocutm_campaignrewrite 遇到字段对不上时优先查它。注意统一 Key 的意义不是「省事」而是让后台请求来源可追溯。当R.jar被占用时你能快速判断是不是某个 AI 工具在后台跑长任务、间接拖住了构建目录。如果你主要做长期编码和 Agent 任务可以看 Coding Planhttps://taotoken.net/coding-plan?utm_sourcetaotoken_aicg_blog_endutm_contentcoding-planutm_campaignrewrite 。只是想验证模型通不通用模型对话页即可https://taotoken.net/models?utm_sourcetaotoken_aicg_blog_endutm_contentmodelsutm_campaignrewrite 。Claude Code 相关接入参考https://taotoken.net/claudecode?utm_sourcetaotoken_aicg_blog_endutm_contentclaudecodeutm_campaignrewrite 。3. 可复制配置gradle.properties、settings.json、config.toml3.1 gradle.properties 骨架先在项目根目录的gradle.properties里加上这几项。核心是让 Gradle 别把 Daemon 留太久并在切换 IDE 前能干净退出。# 关闭长期驻留的 Daemon减少跨 IDE 切换时的句柄残留 org.gradle.daemonfalse # 构建缓存目录独立避免和 Cursor 索引目录互相干扰 org.gradle.cachingtrue org.gradle.configuration-cachefalse # 控制 JVM 内存避免 Worker 进程长时间不退出 org.gradle.jvmargs-Xmx2048m -Dfile.encodingUTF-8 # Android 侧并行构建按机器核数调整 org.gradle.paralleltrue org.gradle.workers.max4org.gradle.daemonfalse是这套方案的关键。Daemon 常驻确实能加速重复构建但在双 IDE 场景下它正是「关掉 Cursor 才好」的常见元凶之一。关掉后每次构建起新进程构建完句柄自然释放。3.2 Cursor 的 settings.json 骨架Cursor 的用户设置文件在%AppData%\Cursor\User\settings.json。针对 Kotlin 语言服务锁R.jar的问题重点是限制它在 Android 工程里的行为。{ kotlin.languageServer.enabled: false, kotlin.completion.enabled: false, files.watcherExclude: { **/build/**: true, **/.gradle/**: true, **/intermediates/**: true }, search.exclude: { **/build: true, **/.gradle: true }, java.import.gradle.enabled: false }kotlin.languageServer.enabled: false直接掐掉fwcd.kotlin拉起的语言服务进程这是最有效的一刀。files.watcherExclude把build和.gradle排除掉减少 Cursor 文件监听对构建产物的句柄占用。java.import.gradle.enabled: false防止 Cursor 自己去触发 Gradle 导入。如果你确实需要 Kotlin 补全可以只在工作区级别禁用而不是全局。在项目里建.vscode/settings.json{ kotlin.languageServer.enabled: false }这样只影响当前 Android 工程其他项目不受影响。3.3 config.toml 骨架AI 工具统一接入如果你用支持 TOML 配置的编码工具把 TaoToken 的统一通道写进去。下面是一个通用骨架字段名按你实际工具调整[provider] name taotoken base_url https://taotoken.net/api api_key sk-你的统一Key [model] default claude-sonnet timeout_seconds 120 [behavior] # 避免后台长任务在构建期间持续占用工作目录 background_tasks false watch_project_files falsebackground_tasks false和watch_project_files false这两项是为了防止 AI 工具在后台持续扫描工程目录、间接持有build下的文件句柄。排查文件锁时先把这两个关掉能排除一大类干扰。4. 验证请求与成功结果配置改完按下面顺序验证。先确认 AI 通道通再确认文件锁解除。4.1 验证 TaoToken 通道用 curl 打一次模型对话接口确认 Key 和基址没问题curl -X POST https://taotoken.net/api/v1/chat/completions \ -H Authorization: Bearer sk-你的统一Key \ -H Content-Type: application/json \ -d { model: claude-sonnet, messages: [{role: user, content: ping}] }返回里带choices字段就说明通道正常。这一步的意义是确认 AI 工具本身能独立工作后面排查文件锁时就能把它排除在外。4.2 复现并定位 R.jar 占用先故意复现一次。在 Cursor 里编辑一个 Kotlin 文件触发语言服务然后切到 Android Studio 执行构建看到R.jar删除失败后打开资源监视器Win R输入resmon切到「CPU」选项卡在「关联的句柄」搜索框输入R.jar。记下占用进程的名称和 PID通常是java.exe。然后用 PowerShell 查它的父进程链Get-CimInstance Win32_Process -Filter ProcessId15464 | Select-Object Name, ProcessId, ParentProcessId, CommandLine把15464换成实际 PID。看CommandLine里有没有fwcd.kotlin、langServerInstall、.cursor这些字样。如果有就是 Cursor 的 Kotlin 语言服务在锁文件如果看到GradleDaemon、GradleWorkerMain那就是 Gradle 侧残留。4.3 解除占用并验证确认是 Cursor 语言服务后在 Cursor 扩展视图里找到 Kotlin发布者fwcd选「Disable (Workspace)」。然后回到 Android Studio 重新构建./gradlew --stop ./gradlew :app:assembleDebuggradlew --stop先清掉可能残留的 Daemon再执行构建。成功的话BUILD SUCCESSFUL会出现R.jar不再报删除失败。之后在 Cursor 里编辑、Android Studio 里构建来回切换也不会再触发锁文件。5. 本篇常见错排查错误一gradlew --stop执行了但没用。说明占用者不是 Gradle Daemon而是 Cursor 的 Kotlin 语言服务。回到 4.2 用资源监视器确认 PID 的父进程看CommandLine是否指向fwcd.kotlin。是的话必须禁用扩展或退出 Cursor--stop管不到它。错误二禁用了 Kotlin 扩展构建还是失败。检查是不是有多个java.exe同时持有句柄。资源监视器里搜R.jar可能列出多个 PID逐个用 PowerShell 查父进程。有时候 Android Studio 自己的 Kotlin 插件也会持有这时在 Android Studio 里File → Invalidate Caches / Restart再试。错误三改了settings.json不生效。Cursor 需要重启才加载新的语言服务配置。改完设置后完全退出 Cursor任务栏右键退出不是关窗口再重新打开。另外确认改的是用户级settings.json还是工作区级两者优先级不同。错误四org.gradle.daemonfalse后构建变慢。这是预期代价。双 IDE 场景下稳定性优先于速度。如果你机器够快、且能保证每次切换 IDE 前手动gradlew --stop也可以把 Daemon 开回来但要养成切换前停 Daemon 的习惯。错误五AI 工具后台任务持续占用目录。回到 3.3 的config.toml确认background_tasks和watch_project_files都是false。如果工具不支持这两项就在构建期间手动暂停它的文件监听功能。提示排查顺序永远是「先定位 PID → 再查父进程 → 再决定停谁」。不要一上来就关 IDE那样你永远不知道真正的占用者是谁。6. 接入与排障的下一步文件锁这类问题定位靠的是进程链不是猜。把 TaoToken 的统一 Key 配好之后AI 工具的请求来源清晰了你就能把「工具后台任务」和「构建文件锁」这两件事分开看。需要创建或管理 Key去 https://taotoken.net/api-keys?utm_sourcetaotoken_aicg_blog_endutm_contentapi-keysutm_campaignrewrite 接入字段对不上查 https://taotoken.net/doc?utm_sourcetaotoken_aicg_blog_endutm_contentdocutm_campaignrewrite 想先验证模型通道用 https://taotoken.net/models?utm_sourcetaotoken_aicg_blog_endutm_contentmodelsutm_campaignrewrite 。长期在 Cursor 里跑编码 Agent 的话Coding Plan 在 https://taotoken.net/coding-plan?utm_sourcetaotoken_aicg_blog_endutm_contentcoding-planutm_campaignrewrite 。最后留一个我常用的习惯每次从 Cursor 切到 Android Studio 做完整构建前先在终端敲一次gradlew --stop再执行构建。这个动作花不了几秒但能省掉大部分「文件被占用」的来回折腾。
返回列表