Android studio 如何在Android Studio中动态生成Java源代码以使用Gradle构建?

Android studio 如何在Android Studio中动态生成Java源代码以使用Gradle构建?,android-studio,gradle,android-gradle-plugin,Android Studio,Gradle,Android Gradle Plugin,作为使用NDK的Android应用程序的一部分,我需要将一些常量从C/C++世界导出到Java中。出于显而易见的原因,我宁愿让它自动化。我正在使用支持NDK的Android Studio 如何从Gradle在应用程序构建时运行的shell脚本动态生成一些.java文件?理想情况下,这个.java文件将放在某个构建中介目录中,而不必放在应用程序源目录中 例如,shell脚本将生成以下Java源代码: public enum Type { FOO, BAR } 从这个C++源: enum

作为使用NDK的Android应用程序的一部分,我需要将一些常量从C/C++世界导出到Java中。出于显而易见的原因,我宁愿让它自动化。我正在使用支持NDK的Android Studio

如何从Gradle在应用程序构建时运行的shell脚本动态生成一些
.java
文件?理想情况下,这个
.java
文件将放在某个构建中介目录中,而不必放在应用程序源目录中

例如,shell脚本将生成以下Java源代码:

public enum Type {
  FOO,
  BAR
}
从这个C++源:

enum class Type {
  FOO,
  BAR
}
以下是我在Android Studio中开始使用的Gradle文件的简化版本供参考:

apply plugin: 'com.android.model.application'

model {

    compileOptions.with {
        sourceCompatibility = JavaVersion.VERSION_1_7
        targetCompatibility = JavaVersion.VERSION_1_7
    }

    android {
        compileSdkVersion = 23
        buildToolsVersion = "23.0.2"

        defaultConfig.with {
            applicationId = "..."
            minSdkVersion.apiLevel = 18
            targetSdkVersion.apiLevel = 23
        }

        defaultConfig.multiDexEnabled = true
    }

    android.ndk {
        platformVersion = "18"
        moduleName = "jni"
        ...
    }

    android.buildTypes {
        release {
            minifyEnabled = false
            proguardFiles.add(file('proguard-rules.txt'))
            ndk.with {
                CFlags.add("-Werror")
                cppFlags.add("-Werror")
            }
        }
    }

    android.productFlavors {
        create("arm7") {
            ndk.abiFilters.add("armeabi-v7a")
        }
    }

}

repositories {
    ...
}

dependencies {
    ...
}

apply plugin: 'com.google.gms.google-services'

您只需将生成的文件写入
$buildDir/generatedJava
,然后将该目录添加为源文件夹。然后使任务
javaCompile
依赖于生成源代码的任务。类似的东西可以在
build.gradle中使用

def outputJavaFile = new File("$buildDir.absolutePath/generatedJava", 'MyEnum.java')
task generateSources(type: Exec) {
    def source = $/
package com.example;
public enum Something {
   One,
   Two
}
/$

    if (!outputJavaFile.parentFile.exists()) {
        outputJavaFile.parentFile.mkdirs()
    }
    outputJavaFile.withWriter {
        it << source
    }
}

compileJava.dependsOn outputJavaFile

sourceSets {
    main {
        java {
            srcDirs 'src/main/java', outputJavaFile.absolutePath
        }
    }
}

// if the goal is to generate the source from a script then just call the script
// inside the Exec closure
task shellScriptToGenerateSources(type: Exec) {
    commandLine 'myShellScript.sh'
}
// then make compileJava depend on the task that runs the script
compileJava.dependsOn shellScriptToGenerateSources

谢谢你。如何通过运行shell脚本而不是内联定义java源代码?请参阅编辑。我添加了一个如何在
type:Exec
closure中运行脚本的示例。您只需使脚本指向
sourceset.main.java.srcDirs
中定义的目录。如果脚本以非零值退出,则任务
shellScriptToGenerateSources
将失败。再次感谢。我只是很难将您的Gradle示例与Android Studio使用的格式相协调(请参阅我的更新问题)-如何将您的更改合并到Android Studio Gradle文件?更新答案以解决您的特定build.Gradle设置
apply plugin: 'com.android.model.application'

// define an output folder for our generated .java files
def GENERATED_JAVA_OUTPUT = "$buildDir/generatedJava"
// if the goal is to generate the source from a script then just call the script
// inside the Exec closure
task shellScriptToGenerateSources(type: Exec) {
    commandLine 'myShellScript.sh'
}
// then make compileJava depend on the task that runs the script
compileJava.dependsOn shellScriptToGenerateSources

model {

    compileOptions.with {
        sourceCompatibility = JavaVersion.VERSION_1_7
        targetCompatibility = JavaVersion.VERSION_1_7
    }

    android {
        compileSdkVersion = 23
        buildToolsVersion = "23.0.2"

        defaultConfig.with {
            applicationId = "..."
            minSdkVersion.apiLevel = 18
            targetSdkVersion.apiLevel = 23
        }

        defaultConfig.multiDexEnabled = true
    }

    android.ndk {
        platformVersion = "18"
        moduleName = "jni"
        ...
    }

    android.buildTypes {
        release {
            minifyEnabled = false
            proguardFiles.add(file('proguard-rules.txt'))
            ndk.with {
                CFlags.add("-Werror")
                cppFlags.add("-Werror")
            }
        }
    }

    android.productFlavors {
        create("arm7") {
            ndk.abiFilters.add("armeabi-v7a")
        }
    }

    // let android know that our java sources shoudl also consider the generated java for the compiler
    android.sourceSet {
        main {
            java {
                srcDir(GENERATED_JAVA_OUTPUT)
            }
        }
    }
}

repositories {
    ...
}

dependencies {
    ...
}

apply plugin: 'com.google.gms.google-services'