在以后的任务可以使用之前,如何阻止gradle删除我的中间文件?

时间:2016-03-26 00:08:06

标签: android android-studio gradle

在我的Android Studio / gradle版本中,我尝试自动生成应用图标。生成图标图像(PNG)的任务正在正确的时间运行,但图像在消耗它的任务运行之前被删除。

这是我已添加到app/build.gradle的简化版本,说明了问题:

task createIcon(type:Exec) {
    def outdir =
        new File("$buildDir/intermediates/res/merged/debug/drawable-ldpi/")
    outputs.dir(outdir)
    if (!outdir.exists()) {
        outdir.mkdirs()
    }
    def svg = 'src/images/ic_launcher.svg'
    inputs.source(new File(svg))
    def png = new File(outdir, "ic_launcher.png")
    outputs.file(png)
    commandLine "$workingDir/svgToPng.sh", svg, png
}

tasks.whenTaskAdded{ t ->
      if(t.name.equals("generateDebugAssets")){
          t.dependsOn createIcon
      }
}

如果我运行./gradlew clean然后./gradlew assembleDebug,我可以看到我的createIcon任务的输出文件," app / build / intermediates / res / merged / debug /drawable-ldpi/ic_launcher.png"已创建,然后很快删除。我从gradlew获得以下输出:

:app:preBuild UP-TO-DATE
:app:preDebugBuild UP-TO-DATE
...
Bitmap saved as: /home/laurence/src/foo/app/build/intermediates/res/merged/debug/drawable-ldpi/ic_launcher.png
:app:generateDebugAssets
:app:mergeDebugAssets
:app:generateDebugResValues UP-TO-DATE
:app:generateDebugResources
:app:mergeDebugResources
:app:processDebugManifest
:app:processDebugResources
/home/laurence/src/foo/app/build/intermediates/manifests/full/debug/AndroidManifest.xml:13:23-44 : AAPT: No resource found that matches the given name (at 'icon' with value '@drawable/ic_launcher').

:app:processDebugResources FAILED

FAILURE: Build failed with an exception.

* What went wrong:
Execution failed for task ':app:processDebugResources'.
> com.android.ide.common.process.ProcessException: org.gradle.process.internal.ExecException: Process 'command '/home/laurence/.local/android-sdks/build-tools/23.0.2/aapt'' finished with non-zero exit value 1

* Try:
Run with --stacktrace option to get the stack trace. Run with --info or --debug option to get more log output.

BUILD FAILED

您可以看到任务:app:processDebugResources失败,因为aapt声称它无法找到@drawable/ic_launcher(我android:iconAndroidManifest.xml的值)它应该对应于我生成PNG的地方。

请注意,我已经确认PNG的生成不仅来自"位图保存为"在控制台输出中行,但也可以在构建期间查看目标目录。文件闪烁存在然后消失片刻。

如果我第二次运行./gradlew assembleDebug构建成功,那就更奇怪了!

如何阻止我生成的PNG被删除,并确保processDebugResources可以看到它而无需运行我的构建两次?

2 个答案:

答案 0 :(得分:1)

我认为您的问题是您正在configuration阶段而不是execution阶段创建目录(更多信息here

请改为尝试:

task createIcon(type:Exec) {
    def svg = 'src/images/ic_launcher.svg'
    def outdir = file("$buildDir/intermediates/res/merged/debug/drawable-ldpi/")
    def png = new File(outdir, "ic_launcher.png")
    inputs.file(svg)
    outputs.dir(outdir)
    commandLine "$workingDir/pngToSvg.sh", png, svg
    doFirst {
        outdir.mkdirs()
    }
}

答案 1 :(得分:1)

事实证明,有两个较小的错误,一个大错误。

一个小错误是pointed out by Lance Java:目录创建是在配置阶段完成的,而不是执行阶段。另一个小错误是它应该与generateDebugResources相关联,而不是generateDebugAssets。然而,修复这些较小的错误并没有解决问题。

最大的错误是文件被写入另一个任务写入的子树。我这样做是因为我不知道如何获取包含在程序集中的文件,但这不是正确的方法,因为写入该子树的其他任务有时会踩到文件(取决于执行任务的顺序),导致它们“消失”。

要解决所有这些问题,第一步是为我们的任务选择一个不会干扰其他任务的新输出目录:

def fromSvgDir = file("$buildDir/generated/fromSvg/")

然后,我们将此srcDirs添加到res文件顶部附近现有android块中的build.gradle

sourceSets {
    main {
        res {
            srcDirs += fromSvgDir
        }
    }
}

最后,让我们的任务使用该目录,并修复其他两个错误:

task createIcon(type:Exec) {
    def outdir = file("$fromSvgDir/drawable-ldpi/")
    outputs.dir(outdir)
    doFirst {
        outdir.mkdirs()
    }
    def svg = file('src/images/ic_launcher.svg')
    inputs.source(svg)
    def png = file("$outdir/ic_launcher.png")
    outputs.file(png)
    commandLine "$workingDir/svgToPng.sh", svg, png
}

tasks.whenTaskAdded{ t ->
      if(t.name.equals("generateDebugResources")){
          t.dependsOn createIcon
      }
}

这是可靠的,并且还具有以下优点:生成的PNG将像非生成的PNG一样通过PNG计算器。