2016-03-26 17 views
1

在我的Android Studio/gradle build中,我试图自动生成我的应用程序图标。生成图标图像(PNG)的任务正在正确的时间运行,但图像在消耗它的任务运行之前正在被删除。在稍后的任务可以使用它们之前,如何阻止gradle删除我的中间文件?

这是什么,我已经添加到我的app/build.gradle这说明该问题的简化版本:如果我运行./gradlew clean然后./gradlew assembleDebug

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 
     } 
} 

,我可以看到我的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:icon值我AndroidManifest.xml),这应该对应于的地方,我正在生成PNG。

请注意,我已经确认PNG不仅是从控制台输出中的“位图另存为”行生成的,还可以通过在构建过程中观看目标目录来生成。该文件眨眼间存在,然后稍后消失。

即使比这更奇怪,如果我第二次运行./gradlew assembleDebug构建成功!

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

回答

1

原来有两个较小的错误和一个大错误。

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

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

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

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

然后我们在这个添加到srcDirsres附近的build.gradle文件顶部现有android块:

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 cruncher。

+1

您应该赞成项目对象上的[file](https://docs.gradle.org/current/javadoc/org/gradle/api/Project.html#file(java.lang.Object))便利方法,而不是明确实例化一个文件对象。例如'def fromSvgDir = file(“$ buildDir/generated/fromSvg /”)''而不是'def fromSvgDir = new File(buildDir,“generated/fromSvg /”)' –

+0

@LanceJava谢谢。我对gradle(和groovy)相当陌生,所以我还不熟悉所有的最佳实践。我已根据您的建议更新了答案。 –

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() 
    } 
} 
+0

谢谢。这看起来像一个错误,但它并没有真正解决我的问题。在摔跤之后,我终于想出了一个解决方案,我已经发布了一个答案。 –

相关问题