Is it possible to declare a variable in Gradle usable in Java?
是否可以在Gradle中声明一个可用于Java的变量?
基本上我想在build.gradle中声明一些变量,然后在构建时获取它(显然)。 就像C / C ++中的预处理器宏一样......
宣言的一个例子就是那样......:
1 2 3 4 5 6 7 8 | android { debug { A_VAR_RETRIEVABLE_IN_JAVA = 42 } release { A_VAR_RETRIEVABLE_IN_JAVA = 42+52 } } |
有没有办法做那样的事情?
生成Java常量
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | 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" } } } |
您可以使用
生成Android资源
1 2 3 4 5 6 7 8 9 10 | android { buildTypes { debug{ resValue"string","app_name","My App Name Debug" } release { resValue"string","app_name","My App Name" } } } |
您可以使用
在Android应用程序中使用Api App Key的示例(Java和XML)
gradle.properties
1 | AppKey="XXXX-XXXX" |
的build.gradle
1 2 3 4 5 6 7 | buildTypes { //... buildTypes.each { it.buildConfigField 'String', 'APP_KEY_1', AppKey it.resValue 'string', 'APP_KEY_2', AppKey } } |
在java代码中的用法
1 2 3 | Log.d("UserActivity","onCreate, APP_KEY:" + getString(R.string.APP_KEY_2)); BuildConfig.APP_KEY_1 |
在xml代码中的用法
1 | <data android:scheme="@string/APP_KEY_2" /> |
- 链接到Android应用程序中Api App Key使用的示例
- 使用由Gradle构建配置生成的字符串常量
使用系统属性的示例,在build.gradle中设置,从Java应用程序中读取(从注释中的问题跟进):
基本上,使用
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 | 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' } |
以下是示例代码的其余部分(您可以推断,但无论如何都包含在此处):它获得系统属性
1 2 3 4 5 6 7 8 9 10 11 12 13 | 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); } } |
测试用例:如果未设置
1 2 3 4 5 6 7 8 9 10 11 12 | 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); } } |
运行(注意:测试正在通过):
1 2 3 4 5 6 7 8 9 10 11 | $ 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 |
我发现棘手的部分实际上是从gradle获取输出...所以,在这里配置日志(slf4j + logback),日志文件显示结果(或者,运行
1 2 3 4 | $ 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 |
如果您注释掉"
1 2 | example.HelloWorldTest > testEnv FAILED org.junit.ComparisonFailure at HelloWorldTest.java:14 |
为完整起见,这是logback配置(
1 2 3 4 5 6 7 8 9 10 11 | <configuration> <file>app.log</file> <layout class="ch.qos.logback.classic.PatternLayout"> <pattern>%d %p %t %c - %m%n</pattern> </layout> </appender> <root level="info"> </root> </configuration> |
文件:
-
build.gradle -
src/main/java/example/HelloWorld.java -
src/test/java/example/HelloWorldTest.java -
src/test/resources/logback-test.xml
您可以在构建期间通过系统环境变量创建可覆盖的构建配置字段:
在开发时使用Fallback,但是当您在Jenkins或其他工具上运行构建时,可以覆盖变量。
在您的app build.gradle中:
1 2 3 4 5 6 7 8 9 10 11 | buildTypes { def serverUrl = '"' + (System.getenv("SERVER_URL")?:"http://default.fallback.url.com")+'"' debug{ buildConfigField"String","SERVER_URL", serverUrl } release { minifyEnabled true proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' buildConfigField"String","SERVER_URL", serverUrl } } |
该变量将以
rciovati的答案是完全正确的我只是想再添加一个小工具,你也可以为build.gradle的默认配置部分中的每个构建类型创建变量。这看起来像这样:
1 2 3 4 5 | android { defaultConfig { buildConfigField"String","APP_NAME",""APP_NAME"" } } |
这将允许您访问通过
1 | BuildConfig.App_NAME |
如果你想要一个通用的配置,也只是想记下这个场景。
我正在使用此代码并且工作得非常好。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 | 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 } } } |
}
如何将函数的String结果插入到buildConfigField中
以下是人类可读格式集的构建日期示例:
1 2 3 4 5 6 7 8 9 | def getDate() { return new SimpleDateFormat("dd MMMM yyyy", new Locale("ru")).format(new Date()) } def buildDate = getDate() defaultConfig { buildConfigField"String","BUILD_DATE",""$buildDate"" } |
上述答案都没有给我任何指导,所以我不得不花两个小时来学习Groovy方法。
我希望能够反对生产,沙箱和当地环境。因为我很懒,我只想在一个地方更改网址。这是我想出的:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | flavorDimensions 'environment' productFlavors { production { def SERVER_HOST ="evil-company.com" buildConfigField 'String', 'API_HOST',""${SERVER_HOST}"" buildConfigField 'String', 'API_URL',""https://${SERVER_HOST}/api/v1/"" buildConfigField 'String', 'WEB_URL',""https://${SERVER_HOST}/"" dimension 'environment' } rickard { def LOCAL_HOST ="192.168.1.107" buildConfigField 'String', 'API_HOST',""${LOCAL_HOST}"" buildConfigField 'String', 'API_URL',""https://${LOCAL_HOST}/api/v1/"" buildConfigField 'String', 'WEB_URL',""https://${LOCAL_HOST}/"" applicationIdSuffix".dev" } } |
替代语法,因为在Groovy方法中只能使用带双引号的
1 2 3 4 5 6 7 | rickard { def LOCAL_HOST ="192.168.1.107" buildConfigField 'String', 'API_HOST', '"' + LOCAL_HOST + '"' buildConfigField 'String', 'API_URL', '"https://' + LOCAL_HOST + '/api/v1/"' buildConfigField 'String', 'WEB_URL', '"https://' + LOCAL_HOST + '"' applicationIdSuffix".dev" } |
我很难理解的是,字符串需要声明为由引号括起来的字符串。由于这个限制,我不能直接使用reference
我正在使用
1 2 3 | buildTypes.each { it.buildConfigField 'String', 'GoogleMapsApiKey',""$System.env.GoogleMapsApiKey"" } |
它基于丹尼斯的答案,但从环境变量中获取。