dskinner dskinner - 9 months ago 24
Android Question

Access sdk.dir value in build.gradle after project evaluation

I have a custom task in my build.gradle file that does bytecode transformations on class files before getting dex'd that looks like this:

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"

The issue with the above is the
classpath sdk.dir + ...
line where
isn't evaluated appropriately. To get this working, I currently have to hard code the path to the

Bonus points if you can answer with an appropriate value to replace
with for accessing a platform specific
based on project configuration. :D


I don't see a published API to expose sdk.dir to your build file, so I just cribbed the code from https://android.googlesource.com/platform/tools/build/+/d69964104aed4cfae5052028b5c5e57580441ae8/gradle/src/main/groovy/com/android/build/gradle/internal/Sdk.groovy to read it manually. As for replacing android-19, if I read android.compileSdkVersion I get that exact string. I'm not sure that this is a published API either, so it may be subject to change and breakage in future versions of the Android Gradle plugin.

With that said, this works for me:

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

If there's no local.properties, this code is going to fail. If you care about that case, you can copy more code from Sdk.groovy to mimic its behavior in trying to find a reasonable default.