在项目评估后在build.gradle中访问sdk.dir的值

22

在我的build.gradle文件中,我有一个自定义任务,它在将类文件转换为dex之前对字节码进行转换,代码如下:

task droidcook(type: JavaExec) {
    main 'org.tsg.android.asm.Main'
}

afterEvaluate { project ->
    android.applicationVariants.each { variant ->
        variant.javaCompile.doLast {
            project.tasks.droidcook.configure {
                classpath variant.javaCompile.classpath
                classpath "build/classes/" + variant.dirName
                classpath sdk.dir + "/platforms/android-19/android.jar"
                classpath "compile-libs/droidcook.jar"
                args "build/classes/" + variant.dirName
                args "com.example"
                // args "-debug"
                // args "-asmifier"
            }
            project.tasks.droidcook.execute()
        }
    }
}
上述的问题在于 classpath sdk.dir + ... 这一行代码,其中 sdk.dir 没有被适当地评估。为了让它正常工作,我目前必须将路径硬编码到 android.jar 中。
如果你能回答一个适当的值来替换 android-19,以便根据项目配置访问特定平台的 android.jar,那就更好了 :D
4个回答

24

我没有看到任何发布的API可以将sdk.dir公开给您的构建文件,所以我只是从 https://android.googlesource.com/platform/tools/build/+/d69964104aed4cfae5052028b5c5e57580441ae8/gradle/src/main/groovy/com/android/build/gradle/internal/Sdk.groovy 中抄袭了代码来手动读取它。至于替换android-19,如果我读取android.compileSdkVersion,我会得到确切的字符串。我不确定这是否也是一个已发布的API,因此它可能会在未来版本的Android Gradle插件中发生更改和故障。

话虽如此,这对我有效:

afterEvaluate {
    def rootDir = project.rootDir
    def localProperties = new File(rootDir, "local.properties")
    if (localProperties.exists()) {
        Properties properties = new Properties()
        localProperties.withInputStream { instr ->
            properties.load(instr)
        }
        def sdkDir = properties.getProperty('sdk.dir')
        def androidJarPath = sdkDir + "/platforms/" + android.compileSdkVersion + "/android.jar"
        print androidJarPath + "\n"
    }
}

如果没有local.properties,这段代码将会失败。如果你关心这种情况,你可以从Sdk.groovy中复制更多的代码来模仿其行为,尝试找到一个合理的默认值。


非常感谢,我曾经因为Gradle而感到疲惫不堪:D 如果我回忆起以前调查这个问题的情况,那么问题就在于sdk目录var是在我的afterEvaluate之后实例化的,因此它不可用。因此,手动加载它可能是目前唯一的解决方案,这对于跨平台开发已经足够好了。 - dskinner
1
println "${android.getSdkDirectory().getAbsolutePath()}" works on 1.5.0在1.5.0版本上,println "${android.getSdkDirectory().getAbsolutePath()}"是可行的。 - Victor Choy

20

有一个简单得多的方法,尽管它没有记录下来,所以可能没有官方支持。

println "${android.getSdkDirectory().getAbsolutePath()}"

奇怪的是,这种方法似乎只适用于某些版本的Gradle插件。它在Scott上面链接的提交中不可用。如果上面的代码无法工作,请尝试这个:

println "${android.plugin.getSdkFolder().getAbsolutePath()}"

为了完整起见,这里也介绍如何获取ndk.dir变量:

println "${android.plugin.getNdkFolder().getAbsolutePath()}"

println "${android.getSdkDirectory().getAbsolutePath()}" 在1.5.0上运行正常。 - Victor Choy

7

从 Android Gradle Plugin v2.1.2 开始,这是我在 Gradle 脚本中使用的内容:

android.ndkDirectory.path
android.sdkDirectory.path

例如,要显式启动ndk-build
task ndkBuild(type: Exec) {
    commandLine android.ndkDirectory.path+'/ndk-build', '-C', file('src/main').absolutePath
}

1

使用:

String androidJar = android.getBootClasspath()[0]

假设您使用的是SDK 21,则此操作将把“<path-to-SDK>/platforms/android-21/android.jar”设置为变量androidJar(自动执行SDK版本选择)。
接下来的步骤显然是用以下内容替换“classpath sdk.dir ...”等:
classpath androidJar

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接