Is it possible to declare a variable in Gradle usable in Java?

后端 未结 9 1219
春和景丽
春和景丽 2020-11-22 09:11

Is it possible to declare a variable in Gradle usable in Java ? Basically I would like to declare some vars in the build.gradle and then getting it (obviously) at build time

相关标签:
9条回答
  • 2020-11-22 09:23

    An example of usage an Api App Key in an Android application (Java and XML)

    gradle.properties

    AppKey="XXXX-XXXX"
    

    build.gradle

    buildTypes {
    //...
        buildTypes.each {
            it.buildConfigField 'String', 'APP_KEY_1', AppKey
            it.resValue 'string', 'APP_KEY_2', AppKey
        }
    }
    

    Usage in java code

    Log.d("UserActivity", "onCreate, APP_KEY: " + getString(R.string.APP_KEY_2));
    
    BuildConfig.APP_KEY_1
    

    Usage in xml code

    <data android:scheme="@string/APP_KEY_2" />
    
    • Link to an example of Api App Key usage in an Android application
    • Using String Constants Generated by Gradle Build Configurations
    0 讨论(0)
  • 2020-11-22 09:23

    I'm using

    buildTypes.each {
        it.buildConfigField 'String', 'GoogleMapsApiKey', "\"$System.env.GoogleMapsApiKey\""
    }
    

    Its based on Dennis's answer but grabs its from an environment variable.

    0 讨论(0)
  • 2020-11-22 09:26

    Here are two ways to pass value from Gradle to use in Java;

    Generate Java Constants

    android {
        buildTypes {
            debug {
                buildConfigField "int", "FOO", "42"
                buildConfigField "String", "FOO_STRING", "\"foo\""
                buildConfigField "boolean", "LOG", "true"
            }
    
            release {
                buildConfigField "int", "FOO", "52"
                buildConfigField "String", "FOO_STRING", "\"bar\""
                buildConfigField "boolean", "LOG", "false"
            }
        }
    }
    

    You can access them with BuildConfig.FOO

    Generate Android resources

    android {
        buildTypes {
            debug{
                resValue "string", "app_name", "My App Name Debug"
            }
            release {
                resValue "string", "app_name", "My App Name"
            }
        }
    }
    

    You can access them in the usual way with @string/app_name or R.string.app_name

    0 讨论(0)
  • 2020-11-22 09:26

    Example using system properties, set in build.gradle, read from Java application (following up from question in comments):

    Basically, using the test task in build.gradle, with test task method systemProperty setting a system property that's passed at runtime:

    apply plugin: 'java'
    group = 'example'
    version = '0.0.1-SNAPSHOT'
    
    repositories {
        mavenCentral()
        // mavenLocal()
        // maven { url 'http://localhost/nexus/content/groups/public'; }
    }
    
    dependencies {
        testCompile 'junit:junit:4.8.2'
        compile 'ch.qos.logback:logback-classic:1.1.2'
    }
    
    test {
      logger.info '==test=='
      systemProperty 'MY-VAR1', 'VALUE-TEST'
    }
    

    And here's the rest of the sample code (which you could probably infer, but is included here anyway): it gets a system property MY-VAR1, expected at run-time to be set to VALUE-TEST:

    package example;
    import org.slf4j.Logger;
    import org.slf4j.LoggerFactory;
    
    public class HelloWorld {
      static final Logger log=LoggerFactory.getLogger(HelloWorld.class);
      public static void main(String args[]) {
        log.info("entering main...");
        final String val = System.getProperty("MY-VAR1", "UNSET (MAIN)");
        System.out.println("(main.out) hello, world: " + val);
        log.info("main.log) MY-VAR1=" + val);
      }
    }
    

    Testcase: if MY-VAR is unset, the test should fail:

    package example;
    ...
    public class HelloWorldTest {
        static final Logger log=LoggerFactory.getLogger(HelloWorldTest.class);
        @Test public void testEnv() {
            HelloWorld.main(new String[]{});
            final String val = System.getProperty("MY-VAR1", "UNSET (TEST)");
            System.out.println("(test.out) var1=" + val);
            log.info("(test.log) MY-VAR1=" + val);
            assertEquals("env MY-VAR1 set.", "VALUE-TEST", val);
        }
    }
    

    Run (note: test is passing):

    $ gradle cleanTest test
    :cleanTest
    :compileJava UP-TO-DATE
    :processResources UP-TO-DATE
    :classes UP-TO-DATE
    :compileTestJava UP-TO-DATE
    :processTestResources UP-TO-DATE
    :testClasses UP-TO-DATE
    :test
    
    BUILD SUCCESSFUL
    

    I've found that the tricky part is actually getting the output from gradle... So, logging is configured here (slf4j+logback), and the log file shows the results (alternatively, run gradle --info cleanTest test; there are also properties that get stdout to the console, but, you know, why):

    $ cat app.log
    INFO Test worker example.HelloWorld - entering main...
    INFO Test worker example.HelloWorld - main.log) MY-VAR1=VALUE-TEST
    INFO Test worker example.HelloWorldTest - (test.log) MY-VAR1=VALUE-TEST
    

    If you comment out "systemProperty..." (which, btw, only works in a test task), then:

    example.HelloWorldTest > testEnv FAILED
        org.junit.ComparisonFailure at HelloWorldTest.java:14
    

    For completeness, here is the logback config (src/test/resources/logback-test.xml):

    <configuration>
        <appender name="FILE" class="ch.qos.logback.core.FileAppender">
            <file>app.log</file>
            <layout class="ch.qos.logback.classic.PatternLayout">
                <pattern>%d %p %t %c - %m%n</pattern>
            </layout>
     </appender>
     <root level="info">
         <appender-ref ref="FILE"/>
    </root>
    </configuration> 
    

    Files:

    • build.gradle
    • src/main/java/example/HelloWorld.java
    • src/test/java/example/HelloWorldTest.java
    • src/test/resources/logback-test.xml
    0 讨论(0)
  • 2020-11-22 09:26

    rciovati's answer is entirely correct I just wanted to add one more tidbit that you can also create variables for every build type within the default config portion of your build.gradle. This would look like this:

    android {
        defaultConfig {
            buildConfigField "String", "APP_NAME", "\"APP_NAME\""
        }
    }
    

    This will allow you to have access to through

    BuildConfig.App_NAME
    

    Just wanted to make a note of this scenario as well if you want a common config.

    0 讨论(0)
  • 2020-11-22 09:31

    I'm using this code and working very fine.

    def baseUrl = '\"http://patelwala.com/myapi/"'
    def googleServerKey = '\"87171841097-opu71rk2ps35ibv96ud57g3ktto6ioio.apps.googleusercontent.com"'
    android {
      buildTypes {
      release {
            minifyEnabled true
            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
            buildConfigField 'String', 'BASE_URL', baseUrl
            buildConfigField 'String', 'web_client_id', googleServerKey
        }
        releasedebug {
            initWith debug
            buildConfigField 'String', 'BASE_URL', baseUrl
            buildConfigField 'String', 'web_client_id' ,googleServerKey
        }
        debug {
    
            buildConfigField 'String', 'BASE_URL', baseUrl
            buildConfigField 'String', 'web_client_id', googleServerKey
        }
     }
    }
    

    }

    0 讨论(0)
提交回复
热议问题