Android Gradle实现所有任务完成后自动下载音频并播放
问题
我希望在Android Gradle的所有任务执行完成后播放音乐,但不清楚如何将其与最后一个任务/事件关联。目前我已实现手动执行下载并播放音乐的功能,相关代码如下(基本可运行):
def tempSound = "/tmp/gradleBuildFinished.wav" task downloadMusic { doLast { println "downloadMusic" def sounds = [ "http://www.xxx.zzz/hos1.wav", "http://www.xxx.zzz/hos2.wav", ] def r = new Random() def soundIndex = r.nextInt(sounds.size()) println "Deleting temp sound: " + delete(tempSound) exec { commandLine("bash", "-c", "curl " + sounds.get(soundIndex) + " > " + tempSound) } } } task playMusic { dependsOn downloadMusic doLast { println "playMusic" assert file(tempSound).exists() ("afplay " + tempSound).execute() } } gradle.buildFinished{ // how to execute playMusic? It will trigger when all tasks are done, right? }
想请教如何在gradle.buildFinished闭包中执行playMusic任务?
解决方案
Gradle的buildFinished回调确实在所有任务执行完成后触发,但此时任务执行阶段已经结束,无法直接调用playMusic.execute()触发任务执行(会抛出异常)。以下是两种可行的实现方式:
方法1:提取逻辑为独立方法,直接在buildFinished中调用
把下载和播放的核心逻辑抽成独立方法,直接在buildFinished里执行,跳过任务机制的限制:
def tempSound = "/tmp/gradleBuildFinished.wav" // 提取下载逻辑为方法 def downloadRandomSound() { println "downloadMusic" def sounds = [ "http://www.xxx.zzz/hos1.wav", "http://www.xxx.zzz/hos2.wav", ] def r = new Random() def soundIndex = r.nextInt(sounds.size()) println "Deleting temp sound: " + delete(tempSound) exec { commandLine("bash", "-c", "curl " + sounds.get(soundIndex) + " > " + tempSound) } } // 提取播放逻辑为方法 def playDownloadedSound() { println "playMusic" assert file(tempSound).exists() ("afplay " + tempSound).execute() } // 保留原任务(方便手动测试) task downloadMusic { doLast { downloadRandomSound() } } task playMusic { dependsOn downloadMusic doLast { playDownloadedSound() } } // 构建完成后自动执行下载和播放 gradle.buildFinished { try { downloadRandomSound() playDownloadedSound() } catch (Exception e) { println "播放音乐失败: ${e.message}" } }
方法2:通过任务依赖让playMusic自动在最后执行
利用Gradle任务图机制,让playMusic成为所有执行任务的最终依赖,确保它在最后运行:
def tempSound = "/tmp/gradleBuildFinished.wav" task downloadMusic { doLast { println "downloadMusic" def sounds = [ "http://www.xxx.zzz/hos1.wav", "http://www.xxx.zzz/hos2.wav", ] def r = new Random() def soundIndex = r.nextInt(sounds.size()) println "Deleting temp sound: " + delete(tempSound) exec { commandLine("bash", "-c", "curl " + sounds.get(soundIndex) + " > " + tempSound) } } } task playMusic { dependsOn downloadMusic doLast { println "playMusic" assert file(tempSound).exists() ("afplay " + tempSound).execute() } } // 任务图准备就绪后,配置playMusic为所有任务的后置依赖 gradle.taskGraph.whenReady { graph -> graph.allTasks.each { task -> if (task != playMusic) { playMusic.mustRunAfter task } } // 确保playMusic被加入执行队列 if (!graph.hasTask(playMusic)) { graph.addTask(playMusic) } }
注意事项
afplay是macOS专属的音频播放命令,Windows环境可替换为start,Linux环境可替换为aplay。- 网络下载可能出现失败,建议添加异常捕获逻辑,避免影响构建完成后的体验。
内容的提问来源于stack exchange,提问作者deadfish
相关产品推荐
相关产品推荐

