Android Studio Gradle:执行静态 Java 方法(从 ANT 到 Gradle 的迁移) [英] Android Studio Gradle: Execute static Java Method (Migration from ANT to Gradle)

查看:39
本文介绍了Android Studio Gradle:执行静态 Java 方法(从 ANT 到 Gradle 的迁移)的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试从构建过程的 build.gradle 脚本 asp 艺术中运行 java 类的静态 main 方法.我使用 Android Studio 1.0.2 和 Android/Gradle 插件'com.android.tools.build:gradle:1.0.0'

我想在构建过程中运行其主要方法的 java 类位于 ...\trunk-gradle\myproject\src\main\java\de\myapp\gradle

package de.myapp.gradle;公共类配置客户{公共静态无效主(字符串 [] args){字符串服务器 = args[0];字符串客户 = args[1];System.out.println(String.format("使用服务器 %s 配置客户 %s", customer, server));}}

之前我用ANT调用java方法如下:

<java failonerror="yes" classname="de.myapp.gradle.ConfigureCustomer"><类路径><path location="${base.dir}/bin/classes/"/></classpath><arg line="${customer}"/><arg line="${server }"/></java>

但是现在我要迁移到 Groovy,所以这里是我的项目 build.gradle 文件的相关部分,它尝试执行上述类的主要方法(实际任务定义在依赖项之前的末尾):

应用插件:'com.android.application'安卓 {project.ext.set("客户", "")project.ext.set("服务器", "")dexOptions {preDexLibraries = false}compileSdkVersion 19构建工具版本21.1.2"默认配置{//默认配置}签名配置{释放 {//发布版本的配置}}构建类型{调试{服务器=测试"}释放 {服务器 = "发布"}}产品风味{客户A{客户 = "a"}客户B{客户 = "b"}客户C{客户 = "c"}}}任务(配置客户,类型:JavaExec){println '正在运行客户配置...'main = 'de.myapp.gradle.ConfigureCustomer'args 客户,服务器}依赖{//依赖设置}

所以现在当我通过命令行(windows)运行以下命令时:

gradew configureCustomer

我收到以下错误消息:

<块引用>

错误:无法找到或加载主类de.myapp.gradle.ConfigureCustomer

我的问题如下:

  1. 如何修复上述错误消息?我是否必须将我的 java 类移动到另一个文件夹?也许在构建脚本中配置某事?
  2. 如何确保在实际编译类之后执行 java 任务?
  3. 如果我想将任务 configureCustomer 作为另一个任务的一部分执行,我是否只需在我的 gradle 的任务定义中编写以下行?

<块引用>

配置客户

我也尝试添加类路径:

task (configureCustomer, type: JavaExec) {println '正在运行客户配置...'main = 'de.myapp.gradle.ConfigureCustomer'类路径 = sourceSets.main.runtimeClasspathargs 客户,服务器}

但我得到的只是一条 gradle 构建错误消息:

<块引用>

在 SourceSet 容器上找不到属性main"

显然,Android Studio 的 Gradle 中不存在sourceSets.main.runtimeClasspath".也许它的名字不同.虽然我也尝试像这样设置类路径:

classpath = '${projectDir.getAbsolutePath()}\\build\\intermediates\\classes\\' + customer + '\\release'

我也试过这个:

classpath = '${projectDir.getAbsolutePath()}\\build\\intermediates\\classes\\' + customer + '\\release\\de\\myapp\\gradle'

这些都不起作用,上面的错误仍然存​​在:

<块引用>

错误:无法找到或加载主类de.myapp.gradle.ConfigureCustomer

解决方案

我终于找到了适用于 Android/Gradle 的东西,但实现起来似乎比本来应该复杂得多.

所以回顾一下 - 这是我想要执行的主要方法的 Java 类:

打包 de.myapp.gradle;

public class ConfigureCustomer {公共静态无效主(字符串 [] args){字符串客户 = args[0];字符串版本名称 = args[1];System.out.println(String.format("使用 versionName %s 配置客户 %s", customer, versionName ));}}

我想对每种风格执行上述操作,并且只针对发布版本(而不是调试版本),所以这是我的任务定义(您仍然必须使您的任务依赖于 gradle 构建任务之一,以便它被执行 -为此,我依赖于 preBuild 任务):

android {//构建类型设置,签名配置和其他东西}//在android块之后我的任务定义如下:任务构建打印输出(类型:JavaExec){android.applicationVariants.all { 变体 ->//为每种口味运行java任务variant.productFlavors.each { 风味 ->println "触发客户配置风味" + flavor.nameif (variant.buildType.name.equals('release')) {//只为发布版本运行java任务//在 android/gradle 中找不到运行时类路径,所以我将在这里直接链接到我的 jar 文件.jarfile 包含我要运行的类(使用 main 方法)classpath += files("libs/my-jarfile.jar")//这是我的类的全限定名,包括包名(de.myapp.gradle)和类名(ConfigureCustomer)main = "de.myapp.gradle.ConfigureCustomer"//传入参数 - 在这种情况下,客户的姓名和应用程序的版本名称(来自 AndroidManifest.xml)args 风味名称,变体.版本名称}}}}

您会注意到我放弃了将我的类集成到我即将构建的 android 项目中的想法.相反,我将该类作为一个单独的项目,构建了一个 jar 文件并将其放入我正在构建的 android 项目的 libs 文件夹中.

更新 04.02.2015

我稍微修改了上面的内容以使用 javaexec 方法而不是 JavaExec 任务类型:

preBuild.doFirst {android.applicationVariants.all { 变体 ->variant.productFlavors.each { 风味 ->if (variant.buildType.name.equals('release')) {javaexec {println "触发客户构建风味" + flavor.nameclasspath += files("libs/my-jarfile.jar")main = "de.myapp.gradle.ConfigureCustomer"args 风味名称,变体.版本名称}println "Done build customer for flavor" + flavor.name}}}}

这是另一种变体,我们在可重用(首选)任务中定义 javaexec,然后将其作为依赖项添加到 preBuild 任务中:

//定义我们的自定义任务并将闭包添加为一个动作任务构建客户<<{android.applicationVariants.all { 变体 ->variant.productFlavors.each { 风味 ->if (variant.buildType.name.equals('release')) {javaexec {println "触发客户构建风味" + flavor.nameclasspath += files("libs/my-jarfile.jar")main = "de.myapp.gradle.ConfigureCustomer"args 风味名称,变体.版本名称}println "Done build customer for flavor" + flavor.name}}}}//使 preBuild 依赖于我们的任务preBuild.dependsOn buildCustomer

如果您有任何问题,请告诉我,我会尽力回答.

I am trying to run the static main method of a java class from my build.gradle script asp art of the build process. I am using Android Studio 1.0.2 with the Android/Gradle Plugin 'com.android.tools.build:gradle:1.0.0'

The java class whose main method I want to run during the build resides in ...\trunk-gradle\myproject\src\main\java\de\myapp\gradle

package de.myapp.gradle;

public class ConfigureCustomer {

    public static void main(String[] args){
        String server = args[0];
        String customer = args[1];
        System.out.println(String.format("Configuring customer %s with server %s", customer, server));
    }
}

Before I used ANT to call that java method as follows:

<java failonerror="yes" classname="de.myapp.gradle.ConfigureCustomer ">
    <classpath>
        <path location="${base.dir}/bin/classes/"/>
    </classpath>
    <arg line="${customer}"/>
    <arg line="${server }"/>
</java>

But now I am migrating to Groovy, so here is the relevant part of my project's build.gradle file that tries to execute the main method of above class (actual task definition is at the end just before the dependencies):

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

    project.ext.set("customer", "")
    project.ext.set("server", "")

    dexOptions {
        preDexLibraries = false
    }

    compileSdkVersion 19
    buildToolsVersion "21.1.2"

    defaultConfig {
//Default configuration
    }


    signingConfigs {
        release {
//Configuration for release builds
        }
    }


    buildTypes {

        debug{
            server = "test"
        }

        release {
            server = "release"
        }
    }

    productFlavors {
        customerA{
            customer = "a"
        }
        customerB{
            customer = "b"
        }
        customerC{
            customer = "c"
        }
    }
}

task (configureCustomer,  type: JavaExec) {
    println 'Running customer configuration...'
    main = 'de.myapp.gradle.ConfigureCustomer'
    args customer, server
}

dependencies {
    //Dependency settings
}

So now when I run the following via the command line (windows):

graldew configureCustomer

I get the following error message:

Error: Could not find or load main class de.myapp.gradle.ConfigureCustomer

My questions hence are as follows:

  1. How do I manage to fix the error message above? Do I have to move my java class to another folder? Maybe configure sth in the build scipt?
  2. How can I make sure the java task is executed after the classes have actually been compiled?
  3. If i wanted to execute the task configureCustomer as part of another task, would I simply write the following line in my gradle's task definition?

configureCustomer

I also tried to add the classpath:

task (configureCustomer,  type: JavaExec) {
    println 'Running customer configuration...'
    main = 'de.myapp.gradle.ConfigureCustomer'
    classpath = sourceSets.main.runtimeClasspath
    args customer, server
}

But all that got me was a gradle build error message saying:

Could not find property "main" on SourceSet container

So apparently "sourceSets.main.runtimeClasspath" does not exist in Android Studio's Gradle. Maybe it's named differently. Though I also tried setting the classpath like this:

classpath = '${projectDir.getAbsolutePath()}\\build\\intermediates\\classes\\' + customer + '\\release'

and I also tried this:

classpath = '${projectDir.getAbsolutePath()}\\build\\intermediates\\classes\\' + customer + '\\release\\de\\myapp\\gradle'

None of which worked, the error from above persists:

Error: Could not find or load main class de.myapp.gradle.ConfigureCustomer

解决方案

I finally found something that works for Android/Gradle but getting there seemed a lot more complicated, than it should have been.

So for recap - here is the Java class whose main method I'd like to execute:

package de.myapp.gradle;

public class ConfigureCustomer {

    public static void main(String[] args){
        String customer = args[0];
        String versionName = args[1];
        System.out.println(String.format("Configuring customer %s with versionName %s", customer, versionName ));
    }
}

I want to execute the above for each flavor and only for release builds (not debug builds) so here is my task definition (you'd still have to make your task depend on one of the gradle build tasks so it's executed - I am depending on the preBuild task for this purpose):

android {
//Build type setup, signing configuration and other stuff
}

//After the android block my task definition follows:

task buildPrintout(type: JavaExec) {
    android.applicationVariants.all { variant ->
    //Runt he java task for every flavor
        variant.productFlavors.each { flavor ->
            println "Triggering customer configuration for flavor " + flavor.name
            if (variant.buildType.name.equals('release')) {
                //Run the java task only for release builds
                //Cant find the runtime classpath in android/gradle so I'll directly link to my jar file here. The jarfile contains the class I want to run (with the main method)
                classpath += files("libs/my-jarfile.jar")
                //This is the fully qualified name of my class, including package name (de.myapp.gradle) and the classname (ConfigureCustomer)
                main = "de.myapp.gradle.ConfigureCustomer"
                //Pass in arguments - in this case the customer's name and the version name for the app (from AndroidManifest.xml)
                args flavor.name, variant.versionName
            }
        }
    }
}

You'll notice that I dumped the idea of having my Class integrated in the android project I am about to build. Instead I made that one class a separate project, built a jar file and dropped it in the libs folder of the android project i am building.

UPDATE 04.02.2015

I have slightly modified the above to use the javaexec method instead of the JavaExec Task type:

preBuild.doFirst {
    android.applicationVariants.all { variant ->
        variant.productFlavors.each { flavor ->
            if (variant.buildType.name.equals('release')) {
                javaexec {
                    println "Triggering customer build for flavor " + flavor.name
                    classpath += files("libs/my-jarfile.jar")
                    main = "de.myapp.gradle.ConfigureCustomer"
                    args flavor.name, variant.versionName
                }
                println "Done building customer for flavor " + flavor.name
            }
        }
    }
}

And here is yet another variation, where we define the javaexec within a reusable (which is preferred) task, that we then add as a dependency to the preBuild task:

//Define our custom task and add the closures as an action
    task buildCustomer << {
        android.applicationVariants.all { variant ->
            variant.productFlavors.each { flavor ->
                if (variant.buildType.name.equals('release')) {
                        javaexec {
                            println "Triggering customer build for flavor " + flavor.name
                            classpath += files("libs/my-jarfile.jar")
                            main = "de.myapp.gradle.ConfigureCustomer"
                            args flavor.name, variant.versionName
                        }
                        println "Done building customer for flavor " + flavor.name
                }
            }
        }        
    }
    //Make preBuild depend on our task
    preBuild.dependsOn buildCustomer

If you have any questions let me know and I'll try to answer them.

这篇关于Android Studio Gradle:执行静态 Java 方法(从 ANT 到 Gradle 的迁移)的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆